# Maselli Sensor to Siemens PLC Communication Implementation ## Introduction This document provides an implementation guide for establishing communication between a Maselli sensor (which uses the ADAM protocol over RS485) and a Siemens S7-315 DP/PN PLC using a Waveshare RS232/485 TO WIFI ETH (B) gateway. This implementation handles the unidirectional communication where data flows from the sensor to the PLC. ## Maselli Protocol with ADAM Overview As per the provided documentation, the Maselli sensor communicates with the following characteristics: - **Maselli UR29**: RS485 with 115200 baud, 8N1 settings - **Maselli UR62**: RS485 with 19200 baud, 8N1 settings - **Communication Type**: Unidirectional (sensor sends data to PLC) - **Data Format**: String with specific format: ``` # XX XX.YYY CkCk Cr ``` Where: - `#` is the start character - `XX` is the ADAM address (2 chars) - `XX.YYY` is the Brix or Temperature value in mA (6 chars) - `CkCk` is the checksum (2 chars) - `Cr` is the carriage return - **Value Range Example**: - 4 mA corresponds to Low Brix value (e.g., 0 Brix) - 20 mA corresponds to High Brix value (e.g., 80 Brix) ## SCL Implementation The following SCL code provides a complete implementation for handling this communication. The implementation consists of multiple parts: 1. A function block for managing TCP/IP communication with the gateway 2. Functions for parsing the Maselli protocol string 3. Functions for scaling the mA value to the appropriate Brix value 4. Configuration functions for the TCP connection ### Main Function Block ```pascal FUNCTION_BLOCK "FB_Maselli_Communications" VAR_INPUT xExecute : BOOL; // Trigger to initiate connection tConnectionID : TCON_IP_v4; // TCP connection parameters END_VAR VAR_OUTPUT xConnected : BOOL; // Connection status xError : BOOL; // Communication error wErrorID : WORD; // Error code rBrixValue : REAL; // Calculated Brix value rTempValue : REAL; // Calculated Temperature value (if applicable) rCurrentmA : REAL; // Received mA value END_VAR VAR // TCP communication variables fbTCON : TCON; // FB for TCP connection fbTRCV : TRCV; // FB for TCP reception xTCONExecute : BOOL; xTRCVExecute : BOOL; wTCONID : WORD := 1; // Connection ID // Buffer and processing variables aRxBuffer : ARRAY[0..255] OF BYTE; // Reception buffer iRxLength : INT; // Received length sRxString : STRING[255]; // Reception string sParsedValue : STRING[6]; // Extracted value as string (XX.YYY) // Parsing variables iState : INT := 0; // Parsing state xNewDataReceived : BOOL := FALSE; // New data flag // Scaling variables rLowBrix : REAL := 0.0; // Low Brix value (4mA) rHighBrix : REAL := 80.0; // High Brix value (20mA) END_VAR VAR CONSTANT START_CHAR : BYTE := 16#23; // '#' in ASCII END_VAR BEGIN // ---- TCP Connection Management ---- IF xExecute AND NOT xConnected THEN xTCONExecute := TRUE; END_IF; // Establish connection fbTCON( EN := TRUE, ENO => , REQ := xTCONExecute, ID := wTCONID, CONNECT := tConnectionID, DONE => xConnected, BUSY => , ERROR => xError, STATUS => wErrorID ); // Reset connection trigger IF xConnected OR xError THEN xTCONExecute := FALSE; END_IF; // ---- Data Reception ---- IF xConnected THEN xTRCVExecute := TRUE; // Receive data fbTRCV( EN := TRUE, ENO => , REQ := xTRCVExecute, ID := wTCONID, LEN := 0, // Adhoc mode (receives whatever is available) DATA := aRxBuffer, RCVD_LEN => iRxLength, DONE => xNewDataReceived, BUSY => , ERROR => xError, STATUS => wErrorID ); // Process received data IF xNewDataReceived AND iRxLength > 0 THEN // Convert data to string for processing sRxString := ''; FOR i := 0 TO iRxLength-1 DO sRxString := CONCAT(IN1 := sRxString, IN2 := CHR(IN := aRxBuffer[i])); END_FOR; // Process Maselli/ADAM protocol ParseMaselliString(sRxString); // Calculate Brix value based on mA value (linear scale) rBrixValue := LinearScale(rCurrentmA, 4.0, 20.0, rLowBrix, rHighBrix); // Reset flag xNewDataReceived := FALSE; END_IF; END_IF; END_FUNCTION_BLOCK ``` ### Parsing Function ```pascal // Function to process the received Maselli/ADAM string FUNCTION "ParseMaselliString" : VOID VAR_INPUT sInputString : STRING; END_VAR VAR_TEMP sCurrentChar : STRING(1); iPos : INT := 0; iParseState : INT := 0; // 0:Waiting for #, 1:Reading addr, 2:Reading value, 3:Reading checksum sAddrStr : STRING(2); sValueStr : STRING(6); sChecksumStr : STRING(2); END_VAR BEGIN // Reset variables sAddrStr := ''; sValueStr := ''; sChecksumStr := ''; // Parse the string character by character FOR iPos := 0 TO LEN(sInputString) - 1 DO sCurrentChar := MID(IN := sInputString, L := 1, P := iPos + 1); CASE iParseState OF 0: // Waiting for start character '#' IF sCurrentChar = '#' THEN iParseState := 1; END_IF; 1: // Reading ADAM address (2 characters) sAddrStr := CONCAT(IN1 := sAddrStr, IN2 := sCurrentChar); IF LEN(sAddrStr) = 2 THEN iParseState := 2; END_IF; 2: // Reading mA value (6 characters, format XX.YYY) sValueStr := CONCAT(IN1 := sValueStr, IN2 := sCurrentChar); IF LEN(sValueStr) = 6 THEN iParseState := 3; // Convert string to real value #rCurrentmA := STRING_TO_REAL(sValueStr); END_IF; 3: // Reading checksum (2 characters) sChecksumStr := CONCAT(IN1 := sChecksumStr, IN2 := sCurrentChar); // Checksum validation not implemented in this simplified example END_CASE; END_FOR; END_FUNCTION ``` ### Scaling Function ```pascal // Function to linearly scale the mA value to Brix FUNCTION "LinearScale" : REAL VAR_INPUT rInput : REAL; // Value to scale (mA) rInMin : REAL; // Input minimum (4mA) rInMax : REAL; // Input maximum (20mA) rOutMin : REAL; // Output minimum (0 Brix) rOutMax : REAL; // Output maximum (80 Brix) END_VAR BEGIN // Linear scaling formula #LinearScale := (rInput - rInMin) * (rOutMax - rOutMin) / (rInMax - rInMin) + rOutMin; // Ensure result is within limits IF #LinearScale < rOutMin THEN #LinearScale := rOutMin; ELSIF #LinearScale > rOutMax THEN #LinearScale := rOutMax; END_IF; END_FUNCTION ``` ### Main Application Block ```pascal // Main application block ORGANIZATION_BLOCK "OB1" VAR_TEMP // Temporary variables END_VAR BEGIN // Configure TCP connection "ConfigureTCPConnection"(); // Process Maselli data "FB_Maselli_Communications"( xExecute := TRUE, tConnectionID := "g_tConnection" ); // Additional code to use Brix values can be added here END_ORGANIZATION_BLOCK ``` ### Connection Configuration Function ```pascal // Function to configure TCP connection parameters FUNCTION "ConfigureTCPConnection" : VOID VAR_GLOBAL g_tConnection : TCON_IP_v4; // Global variable for connection parameters END_VAR BEGIN // Configure TCP connection parameters g_tConnection.InterfaceId := 64; // Ethernet interface ID (verify in hardware) g_tConnection.ID := 1; // Connection ID g_tConnection.ConnectionType := 11; // Connection type: TCP g_tConnection.ActiveEstablished := TRUE; // PLC initiates connection // IP and port of Waveshare gateway g_tConnection.RemoteAddress.ADDR[1] := 192; // IP Address: 192.168.x.x g_tConnection.RemoteAddress.ADDR[2] := 168; // Adjust according to gateway IP g_tConnection.RemoteAddress.ADDR[3] := 1; // Adjust according to gateway IP g_tConnection.RemoteAddress.ADDR[4] := 10; // Adjust according to gateway IP g_tConnection.RemotePort := 8899; // Default gateway port // Local port for TCP connection g_tConnection.LocalPort := 2000; // Arbitrary local port END_FUNCTION ``` ## Configuration Guide To implement this solution, follow these steps: ### 1. Configure the Waveshare Gateway Configure the Waveshare RS232/485 TO WIFI ETH (B) gateway in transparent transmission mode with these parameters: - **For UR29 sensor**: - RS485: 115200 baud, 8N1 - TCP Server mode (recommended) - Fixed IP address on your network - **For UR62 sensor**: - RS485: 19200 baud, 8N1 - TCP Server mode (recommended) - Fixed IP address on your network ### 2. PLC Configuration - Import the SCL code into your TIA Portal project - Adjust the IP address settings in the `ConfigureTCPConnection` function to match your gateway's IP - Modify the `rLowBrix` and `rHighBrix` values according to your specific application requirements - Configure the Ethernet port of the S7-315 PLC to be on the same subnet as the gateway ### 3. Verification After implementing the code: - Monitor the `xConnected` output to verify the connection status - Check the `rBrixValue` output to see the converted Brix values - Use the `xError` and `wErrorID` outputs for troubleshooting if connection issues occur ## Additional Notes - This implementation focuses on handling the reception of data in the specified Maselli/ADAM format - The checksum validation is not implemented in this example but could be added for improved reliability - For optimal performance, ensure the network connection between the PLC and the gateway is stable - Consider adding watchdog functionality to detect communication failures