Lasse Hedeby

Sharing my passion for automation, programming, IT and other geeky stuff

A CAB printer can receive print jobs via Ethernet Raw using it’s own JScript syntax. Each command is separated by a line.

In order to do this from a SIMATIC S7-300 PLC, I’ve made an array of string (1-20) representing each line. Then the commands can be written directly in the code, and with CONCAT function dynamic data from tags can be added.

 //
 // Generate lines
 //
 statLines[1] := 'J';                                               // Line of JScript
 statLines[2] := 'S l1;0,0,50,53,85;ErrLbl';                        // Line of JScript
 statLines[3] := 'H 125,0,T,R0,B0';                                 // Line of JScript
 statLines[4] := 'O R,P';                                           // Line of JScript
 statLines[5] := 'T 0,7.77,0,3,4,u,k,q80;[J:c38.25]Production ID';  // Line of JScript
 statTempLine := 'B 8.16,12.58,0,datamatrix,1;';                    // 1. part of line of JScript
 statLines[6] := CONCAT(IN1:=statTempLine,IN2:=statProductCode);    // Combine 1. part with product code
 statLines[7] := 'T 36.16,8.02,0,3,4,u,k,q80;[J:c48.84]Error Code'; // Line of JScript
 statTempLine := 'T 37.6,14.64,0,3,6,k,q80;[J:c47.4]';              // 1. part of line of JScript
 statLines[8] := CONCAT(IN1:=statTempLine,IN2:=statErrorCode);      // Combine 1. part with error code
 statTempLine := 'T 0,46.47,0,3,4,k,q80;[J:c78.93]';                // Line of JScript
 statLines[9] := CONCAT(IN1:=statTempLine,IN2:=statProductCode);    // Combine 1. part with product code
 statLines[10] := 'G38.59,3.52,0;R:44.26,38.33,0.2,0.2';            // Line of JScript
 statLines[11] := 'A 1';                                            // Line of JScript 
 statLines[12] := '';
 statLines[13] := '';
 statLines[14] := '';
 statLines[15] := '';
 statLines[16] := '';
 statLines[17] := '';
 statLines[18] := '';
 statLines[19] := '';

Now each line can be combined into a array of characters and send as a TCP telegram using the T-Blocks (TCON, TSEND, TRCV etc.). What I do is to run a loop through each line and move each character to an array. At the end of each line I add a Carriage Return (0xD) to the array.

 // Convert all lines to array of charactors for telegram handling
 FOR statIndexLines := 1 TO 11 DO
   // Find length of string
   statStringLength := LEN(statLines[statIndexLines]);
 
   // Run through string and move every charactor to array
   IF (statStringLength <> 0) THEN
    FOR statIndexLength := 1 TO statStringLength DO
     // Get charactor from string and move to array of charactors
     statSendCharactors[statMemoryCharIndex] := STRING_TO_CHAR(MID(IN:=statLines[statIndexLines],L:=1,P:=statIndexLength));
 
     // Increment charactor index for every cycle
     statMemoryCharIndex := (statMemoryCharIndex + 1);
    END_FOR;
   END_IF;
 
   // Add Carriage Return after each line
   statSendCharactors[statMemoryCharIndex] := '$R';
   // Increment charactor index
   statMemoryCharIndex := (statMemoryCharIndex + 1); 
 END_FOR;

The block itself handles the TCP/IP communication and acts as client.

Attachements:

 

August 3rd, 2016

Posted In: Automation, IT, S7-300/400, SIMATIC, Structured Text (SCL/ST)

Tags: , , , , ,

In a project I needed information in a SIMATIC S7-300 PLC from a Data Matrix code containing a string with values separated by semicolon, like this

Value1;Value2;Value3;Value4

Because of the different length of each value I could not just read data from a fixed byte position, but had to search for the right position in the string to read from. And after that I didn’t knew the length of the value I had to read.

I came up with this;

//================================================================================================
// Hedeby.Net
// (c)Copyright 2015 All Rights Reserved
//------------------------------------------------------------------------------------------------
// file name:        ReadDataMatrix
// created by:       LHH
// library:          -
// system:           Simatic S7-300 V3.3
// version:          Step 7 V5.5
// restrictions:     Cyclic task
// requirements:     -
// functionality:    This function block read the data matrix string from Jumo sensor and returns
//                   the selected strings
//================================================================================================
// Compiler Options
//================================================================================================
{
OverwriteBlocks          := 'y'; // Overwrite the blocks
GenerateReferenceData    := 'y'; // Generate reference data
CreateObjectCode         := 'y'; // Create the object code
OptimizeObjectCode       := 'y'; // Optimize the object code
MonitorArrayLimits       := 'n'; // Monitor the array limits
CreateDebugInfo          := 'n'; // Create the debug info
SetOKFlag                := 'n'; // Set the OK flag
SetMaximumStringLength   := '254' // Maximum string length
}
//================================================================================================
// Change Log:
//------------------------------------------------------------------------------------------------
// Version  Date          Author   Description
//------------------------------------------------------------------------------------------------
// 0.1      2015.09.02    LHH      Created
// 1.0      2015.09.02    LHH      First release after testing
//
//================================================================================================
FUNCTION_BLOCK ReadDataMatrix

TITLE = 'Read Data Matrix'
VERSION: '1.0'
AUTHOR: LHH

VAR_INPUT
 valueIndex        : INT;
 arrData           : ARRAY[1..520] OF CHAR;
END_VAR

VAR_OUTPUT
 valueOutput       : STRING;
END_VAR

VAR
 statIndex         : INT;
 statFieldNumber   : INT;
END_VAR

 statFieldNumber := 0;
 valueOutput := '';
 
 // Run through array of charactors
 FOR statIndex := 1 TO 520 DO
   // Read value index
   IF (valueIndex = statFieldNumber) AND NOT (arrData[statIndex] = ';') THEN
     valueOutput := CONCAT(IN1:=valueOutput,IN2:=CHAR_TO_STRING(arrData[statIndex]));
   END_IF;
 
   // Find separator
   IF (arrData[statIndex] = ';') THEN
     statFieldNumber := (statFieldNumber + 1);
   END_IF;
 
   // Stop when reached
   IF (valueIndex < statFieldNumber) THEN
     EXIT;
   END_IF;
 END_FOR;
END_FUNCTION_BLOCK

The code is searching through the array of charactors to find the separator “;”.  If valueIndex is equal to the actual field number the valueOutput is generated by adding a single character to the end of the string until the next separator i found.

When the valueIndex is reached the search stops to save cycle time.

February 19th, 2016

Posted In: Automation, S7-300/400, SIMATIC, Structured Text (SCL/ST)

Tags: , , , ,