Sending a string over Profinet?

Looking to send two strings (representing employee badge numbers) over profinet from one PLC to another. In my profinet input / output arrays I have allocated 4 bytes per string that I want to send. ie. PN_INPUTS / PN_OUTPUTS are my profinet arrays and bytes 4,5,6,7 are for the first employee badge number (program variable: ACTIVEC1) and bytes 8,9,10,11 are for the second employee badge number (program variable: ACTIVEC2) The strings (employee badge numbers) to be sent are always a 6 digit number. Example ‚012345‘ I have two string variables in my program: ACTIVEC1 and ACTIVEC2 that store the 6 digit numbers in string format. When reading badge numbers in from profinet, CREW1HOLDER and CREW2HOLDER are just temporary string variables that are placeholders for the BUF_TO_STRING functions that I am using to retrieve the strings from the profinet input arrays. Once the BUF_TO_STRING function writes the badge numbers to the temporary placeholders they will be used to populate the program variables ACTIVEC1 and ACTIVEC2 Similarly, when writing to the profit output arrays, I am using STRING_TO_BUF function. I have created a custom data type of 4 bytes to temporarily populate using STRING_TO_BUF before writing to the PN_OUTPUTS array to avoid any sort of unexpected overflow into the profinet bytes where these numbers do not belong. These buffers are CREW1BUFFER and CREW2BUFFER Working in structured text to do this, so far I have the following… there is some extra logic in here that isn’t necessary for transferring the string from one plc to the other, just ignore that. When in debug mode in PLCnext Engineer, I can see that the BUF_TO_STRING.DONE booleans are flip flopping back and forth as expected. My logic has them constantly running (REQ := NOT(BUF_TO_STRING1.DONE)) However, the STRING_TO_BUF.DONE variables are always FALSE despite having the same sort of logic applied to them. I don’t think the STRING_TO_BUF functions are running properly… any guidance or perhaps a simple example I can build off of would be very much appreciated. //************ RETRIEVE BADGE NUMBERS FROM OTHER PLC ******************************** //THIS HAS TO GO BEFORE THE FUNCTION BLOCK BUF_TO_STRING CALLS SO IT CATCHES A 'DONE' BEFORE THE PROCESS STARTS AGAIN IF BUF_TO_STRING1.DONE THEN //WHEN THE FUNCTION IS COMPLETE IF ACTIVEC1 = '' THEN //IF THE LOCAL ACTIVE1 IS BLANK ACTIVEC1 := CREW1HOLDER; //SET THE ACTIVE CREW 1 TO THE INCOMING CREW 1 BADGE (COULD STILL BE BLANK FROM OTHER PLC) ELSIF UNLOCKC1 = FALSE THEN //ELSE, CREW 1 IS CURRENTLY ACTIVE AND POPULATED... WAIT UNTIL THE LOGIN TIMER EXPIRES IF BAC1 = FALSE AND BBC1 = FALSE AND IMP = FALSE THEN //THEN IF NOBODY IS USING CREW 1 LIGHTS, RESET THE ACTIVE C1 TO BLANK ACTIVEC1 := ''; //LOGIN PROGRAM ALSO CLEARS THIS VARIABLE, BUT ONLY WHEN LOGIN TIMER EXPIRES OR END_IF //LOGIN PAGE IS INSTANTIATED. THIS WILL CLEAR ACTIVE C1 ON THIS PLC EVEN IF OTHER PLC IS ONLY ONE BEING USED. END_IF END_IF IF BUF_TO_STRING2.DONE THEN IF ACTIVEC2 = '' THEN ACTIVEC2 := CREW2HOLDER; ELSIF UNLOCKC2 = FALSE THEN IF BAC2 = FALSE AND BBC2 = FALSE AND IMP = FALSE THEN ACTIVEC2 := ''; END_IF END_IF END_IF //NOW WE CAN CALL THE BUF_TO_STRING FUNCTION TO GRAB THE BADGE NUMBER FROM BYTE ARRAY AND CONVERT TO STRING BUF_TO_STRING1( REQ := NOT(BUF_TO_STRING1.DONE), //SHOULD START AND RESET ITSELF CONTINOUSLY... BUF_OFFS := 4, //ACTIVE CREW 1 STARTS AT BYTE 4 BUF_CNT := 4, //FOUR BYTES WERE ALLOTED TO BADGE NUMBERS BUFFER := PN_INPUTS, //POINT IT OT THE INPUT ARRAY DST := CREW1HOLDER //DESTINATION IS THE HOLDER VARIABLE ); BUF_TO_STRING2( REQ := NOT(BUF_TO_STRING2.DONE), BUF_OFFS := 8, BUF_CNT := 4, BUFFER := PN_INPUTS, DST := CREW2HOLDER ); //************ WRITE ACTIVE BADGE NUMBERS TO OUTPUT PORT ******************************** //THIS WILL CONSTANTLY WRITE THE ACTIVE CREW 1 AND CREW 2 BADGE NUMBERS TO OUTPUT PORT //THE RECEIVING PLC WILL DETERMINE WHAT TO DO WITH THIS INFORMATION //CUSTOM DATA TYPE OF BYTEARRAY4 WAS CREATED TO STORE THE STRING_TO_BUF OUTPUTS SUCH THAT 4 BYTES ARE ONLY EVER WRITTEN //THIS AVOIDS OVERFLOW INTO THE NEXT BYTES OF THE PN_OUTPUT DATA STRUCTURE IF SOMETHING GOES WRONG //SIMILAR TO THE READ IN PROCESS ABOVE, THIS HAS TO GO BEFORE THE STRING TO BUF FUNCTION TO GET THE //DATA BEFORE THE CALL TO THE FUNCTION BLOCK RESETS ITSELF AND IS LOST. IF STRING_TO_BUF1.DONE THEN PN_OUTPUTS[4] := CREW1BUFFER[0]; PN_OUTPUTS[5] := CREW1BUFFER[1]; PN_OUTPUTS[6] := CREW1BUFFER[2]; PN_OUTPUTS[7] := CREW1BUFFER[3]; END_IF IF STRING_TO_BUF2.DONE THEN PN_OUTPUTS[8] := CREW2BUFFER[0]; PN_OUTPUTS[9] := CREW2BUFFER[1]; PN_OUTPUTS[10] := CREW2BUFFER[2]; PN_OUTPUTS[11] := CREW2BUFFER[3]; END_IF //NOW WE CAN USE STRING TO BUF TO WRITE THE ACTIVE CREWS TO THE BUFFER STRING_TO_BUF1( //CALL THE FUNCTION REQ := NOT(STRING_TO_BUF1.DONE), //WHEN THE FUNCTION HAS COMPLETED THIS WILL RESTART IT AGAIN NEXT TIME THROUGH BUF_OFFS := 0, //START WRITING TO THE BUFFER AT POSITION 0 BUF_CNT := 4, //WRITE 4 BYTES SRC := ACTIVEC1, //SOURCE IS THE ACTIVE CREW 1 BUFFER := CREW1BUFFER //DESTINATION BUFFER IS THE CREW 1 BUFFFER ); STRING_TO_BUF2( REQ := NOT(STRING_TO_BUF2.DONE), BUF_OFFS := 0, BUF_CNT := 4, SRC := ACTIVEC2, BUFFER := CREW2BUFFER );

pic 1.JPG
pic 2.JPG
example.jpg
example.jpg

Hello doublec4, the FB „STRING_TO_BUF“ needs more as one cyclic to finish the operation and I assume, the self called operation can be cause of this behavoir. Please try this not tested code, it should work (BUF_TO_STRING programming is similar to a STRING_TO_BUF). If not please let me know. (* 1. Define the Struct in DataTypes sheet and declare the Variable „udtStringToBuf1“ of this struct type in your program ) UDT_STRING_TO_BUF : STRUCT \t\t( Inputs ) \t\txREQ\t\t: BOOL; \t\txBUF_FORMAT\t: BOOL; \t\tiBUF_OFFS\t: INT; \t\tiBUF_CNT\t: INT; \t\t( Outputs ) \t\txDONE\t\t: BOOL; \t\txERROR\t\t: BOOL; \t\tiSTATUS\t\t: INT; \t\t( Inouts ) \t\t(** \t\tSRC := ANY, \t\tBUFFER := ANY \t\t***) \tEND_STRUCT; (* 2. define one or two Instance’s of STRING_TO_BUF in separate code sheet ) STRING_TO_BUF_X1 ( \t( Inputs ) \tREQ\t\t\t:= udtStringToBuf1.xREQ, \tBUF_FORMAT\t:= udtStringToBuf1.xBUF_FORMAT, \tBUF_OFFS\t := udtStringToBuf1.iBUF_OFFS, \tBUF_CNT\t\t:= udtStringToBuf1.iBUF_CNT, \t( Outputs ) \tDONE\t\t=> udtStringToBuf1.xDONE, \tERROR\t\t=> udtStringToBuf1.xERROR, \tSTATUS\t\t=> udtStringToBuf1.iSTATUS, \t( Inouts ) \tSRC\t := strContent, \tBUFFER\t\t:= arrPNData ); ( 3. Add following code in your program*) CASE iState OF \t0: (* First String ) \t\tstrContent1 := ‚123456‘; \t\tudtStringToBuf1.iBUF_CNT := LEN(strContent1); udtStringToBuf1.iBUF_OFFS = 0; \t\tudtStringToBuf1.xREQ := TRUE; \t\tIF(udtStringToBuf1.xDONE = TRUE) THEN \t\t\tudtStringToBuf1.xREQ := FALSE; \t\t\tiState:= 1; \t\tEND_IF; \t1: ( End *) \t\tiState := 0; END_CASE; Best Regards Eduard

Thanks I will give that a try, however, as per your comment about it needing more than one cycle to complete, wouldn’t my code still work? For the duration of time that the FB is not complete, the following statement would continue to evaluate to true REQ := NOT(BUF_TO_STRING1.DONE allowing the FB to continue to run cycle after cycle. The preceding piece of code that checks if BUF_TO_STRING1.DONE is true would then catch the FB in the completed state (and process the buffer) before the next call to BUF_TO_STRING where REQ := NOT(BUF_TO_STRING1.DONE would evaluate false, reset the FB, and then the next time through start the process again.

Also, in your CASE statement, should it not read: CASE iSTATUS OF Thank you

Hello doublec4, I tested the code that I send you yesterday and it works fine for me. Please find the Project under following Link: Adresse:\thttps://extrans.phoenixcontact.com/extrans2/index.jsp?id=1562264620 Passwort: S61Kn4WC9e Best Regards Eduard

STRING_TO_BUF.PNG
TestStringToBuf.gif
STRING_TO_BUF_1.PNG