Store PLCnext CommunityPLCnext on LinkedInPLCnext on Instagram  PLCnext on YouTube Github PLCnext CommunityStore PLCnext Community

  1. doublec4
  2. PLCnext Engineer
  3. Monday, 12 July 2021
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
);

Eduard PLCnext Team Accepted Answer Pending Moderation
0
Votes
Undo
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
(* Inputs *)
xREQ : BOOL;
xBUF_FORMAT : BOOL;
iBUF_OFFS : INT;
iBUF_CNT : INT;
(* Outputs *)
xDONE : BOOL;
xERROR : BOOL;
iSTATUS : INT;
(* Inouts *)
(***
SRC := ANY,
BUFFER := ANY
***)
END_STRUCT;

(* 2. define one or two Instance's of STRING_TO_BUF in separate code sheet *)

STRING_TO_BUF_X1 (
(* Inputs *)
REQ := udtStringToBuf1.xREQ,
BUF_FORMAT := udtStringToBuf1.xBUF_FORMAT,
BUF_OFFS := udtStringToBuf1.iBUF_OFFS,
BUF_CNT := udtStringToBuf1.iBUF_CNT,
(* Outputs *)
DONE => udtStringToBuf1.xDONE,
ERROR => udtStringToBuf1.xERROR,
STATUS => udtStringToBuf1.iSTATUS,
(* Inouts *)
SRC := strContent,
BUFFER := arrPNData
);

(* 3. Add following code in your program*)

CASE iState OF
0: (* First String *)
strContent1 := '123456';
udtStringToBuf1.iBUF_CNT := LEN(strContent1);
udtStringToBuf1.iBUF_OFFS = 0;
udtStringToBuf1.xREQ := TRUE;
IF(udtStringToBuf1.xDONE = TRUE) THEN
udtStringToBuf1.xREQ := FALSE;
iState:= 1;
END_IF;
1: (* End *)
iState := 0;
END_CASE;


Best Regards
Eduard
Phoenix Contact Electronics Headquarter - PLCnext Runtime Product Management and Support
doublec4 Accepted Answer Pending Moderation
0
Votes
Undo
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.
doublec4 Accepted Answer Pending Moderation
0
Votes
Undo
Also, in your CASE statement, should it not read:

CASE iSTATUS OF

Thank you
Eduard PLCnext Team Accepted Answer Pending Moderation
0
Votes
Undo
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: https://extrans.phoenixcontact.com/extrans2/index.jsp?id=1562264620
Passwort: S61Kn4WC9e

Best Regards
Eduard
Attachments (3)
Phoenix Contact Electronics Headquarter - PLCnext Runtime Product Management and Support
  • Page :
  • 1


There are no replies made for this post yet.
However, you are not allowed to reply to this post.