Lasse Hedeby

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

JSON is a very powerful and simple way of arranging data and exchange it between systems.

https://www.json.org/
https://www.w3schools.com/js/js_json_intro.asp

JSON parser comes for almost every PC based programming language, but not PLC’s, so I started my own.

This parser can read and write JSON in Siemens SIMATIC S7-12xx/S7-15xx PLC’s.
There are some limitations though;

Only strings, numbers and booleans are supported.
No spaces between characters.

 
// Test string 
#tempJSON := '{"name":"Lasse","age":35,"sex":"male","birthDay":"1984-03-02"}'; 
// Convert string to Char array 
Strg_TO_Chars(Strg:=#tempJSON,              
              pChars:=0,               
              Cnt=>#tempCnt,               
              Chars:=#tempChar); 
// Read JSON
"gFBJSONRead"(json:=#tempChar); 

JSON is very useful when systems has to exchange data in e.g. TCP/IP socket communication. Traditionally data exchange has to be documented and agreed on between systems, to have the same data structure for the byte stream. With JSON, this is not needed anymore, and the data and values can be arranged differently but, still understood on all systems.

Attachments:

April 15th, 2019

Posted In: Automation, S7-1200/1500, SIMATIC, Structured Text (SCL/ST)

Tags: , , , ,

Simple CRC32 function for SIMATIC controllers.


FUNCTION "FCCRC32Calc" : DWord
  { S7_Optimized_Access := 'TRUE' }
  VERSION : 0.1
  VAR_INPUT
    data : Array[0..4095] of Byte;
    length : Int;
  END_VAR

  VAR_TEMP
    rem : DWord;
    i : Int;
    j : Int;
  END_VAR

  VAR CONSTANT
    POLYNOMIAL : DWord := 16#ABCDEF01;  // Chose your polynomial here
  END_VAR

  BEGIN
  #rem := 16#ffffffff;
  FOR #i := 0 TO (#length-1) DO
    #rem := #rem XOR #data[#i];
    FOR #j := 0 TO 7 DO
      IF #rem.%X31 THEN // if leftmost (most significant) bit is set
        #rem := SHR(IN := #rem, N := 1) XOR #POLYNOMIAL;
      ELSE
        #rem := SHR(IN := #rem, N := 1);
      END_IF;
    END_FOR;
  END_FOR;
  #FCCRC32Calc := #rem XOR 16#ffffffff;
END_FUNCTION

If the function does not work as expected, it’s often because the endianess is not correct between sender and receiver. Change the #rem.%X31 bit to #rem.%X0 to see if it helps.

March 28th, 2018

Posted In: Automation, Coding, S7-1200/1500, Security, SIMATIC, Structured Text (SCL/ST)

Tags: , , ,

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: , , , , ,

Next Page »