# Using IO-Link Terminal 750-1657 with PFC200

**URL:** <https://www.wago.community/t/io-link-klemme-750-1657-am-pfc200-nutzen/2602>\
**Category:** CODESYS\
**Tags:** codesys\
**Created:** [February 27, 2026, 10:50am UTC](https://www.wago.community/t/io-link-klemme-750-1657-am-pfc200-nutzen/2602 "2026-02-27T10:50:33Z")\
**Posts on this page:** 6\
**Page:** 1

<div class="post-metadata">

**Author:** ![bwurst](https://avatars.discourse-cdn.com/v4/letter/b/91b2a8/32.png) [@bwurst](https://www.wago.community/u/bwurst)\
**Post date:** [February 27, 2026, 10:50am UTC](https://www.wago.community/t/io-link-klemme-750-1657-am-pfc200-nutzen/2602/1 "2026-02-27T10:50:33Z")

</div>

Hello.

I am programming a 750-8212 with several classic I/O terminals using CODESYS 3.5, and so far this works fine.

Now I wanted to connect a flow meter via IO-Link to read out the totalizer. For this, I purchased a 750-1657.

I downloaded IO-Check, used it to identify the IO-Link master on the PLC, and configured it with the IODD file. There, I can immediately see the sensor’s process data.

In CODESYS, I can add the 1657 to the K-Bus (but only by selecting the byte length); however, it then remains completely non-functional and empty—no I/O image is present, and I see no payload data. I can load the IODD file into CODESYS via the device repository, but I don’t know how to get it into the device tree. No matter where I try, the IO-Link device does not appear when I select “Attach Device.”

Which crucial step am I missing here?

---

<div class="post-metadata">

**Author:** ![JohnDitter](https://sea2.discourse-cdn.com/flex016/user_avatar/www.wago.community/johnditter/32/68_2.png) [@JohnDitter](https://www.wago.community/u/JohnDitter)\
**Post date:** [February 27, 2026, 2:29pm UTC](https://www.wago.community/t/io-link-klemme-750-1657-am-pfc200-nutzen/2602/2 "2026-02-27T14:29:28Z")

</div>

Attached are two CODESYS sample projects and an application note from WAGO’s Download Center under the Learning Materials link.

[a2019002\_en\_\_CDS3\_WagoAppIOLink.pdf](https://www.wago.community/uploads/short-url/s7IkF2pqA26LlkNSMa08Ks54dm6.pdf) (519.6 KB)

[WagoAppIOLink\_Example\_02.project](https://www.wago.community/uploads/short-url/kL1rCROJJKGONG0Y58tHAqhiElr.project) (843.7 KB)

[WagoAppIOLink\_Example\_01.project](https://www.wago.community/uploads/short-url/eaxyiFgMrDGMsZw5cDMHDK2FW6P.project) (1014.9 KB)

---

<div class="post-metadata">

**Author:** ![bwurst](https://avatars.discourse-cdn.com/v4/letter/b/91b2a8/32.png) [@bwurst](https://www.wago.community/u/bwurst)\
**Post date:** [March 2, 2026, 4:09pm UTC](https://www.wago.community/t/io-link-klemme-750-1657-am-pfc200-nutzen/2602/3 "2026-03-02T16:09:30Z")

</div>

Thank you for your reply, John!

I managed to solve the issue with the help of the example projects.

It took me the whole weekend but now I have the live data in form of a bytes array that I can split and build some REAL values from them so I have the data I need. I hoped this would be a bit more comfortable but it works.

---

<div class="post-metadata">

**Author:** ![GombasG](https://avatars.discourse-cdn.com/v4/letter/g/3d9bf3/32.png) [@GombasG](https://www.wago.community/u/GombasG)\
**Post date:** [June 17, 2026, 8:33am UTC](https://www.wago.community/t/io-link-klemme-750-1657-am-pfc200-nutzen/2602/4 "2026-06-17T08:33:47Z")

</div>

Hello!

Could you maybe post your solution? I managed to run into the same problem, using 1657 card to read out flow meters 🙂

Thx in advance,

---

<div class="post-metadata">

**Author:** ![bwurst](https://avatars.discourse-cdn.com/v4/letter/b/91b2a8/32.png) [@bwurst](https://www.wago.community/u/bwurst)\
**Post date:** [June 17, 2026, 9:01am UTC](https://www.wago.community/t/io-link-klemme-750-1657-am-pfc200-nutzen/2602/5 "2026-06-17T09:01:04Z")

</div>

Hello.  
I am happy to post my code here.  
Of course, as always, with the note that this is my first CODESYS project and that there is certainly a better way to do it. But it works.

I have split it into two files, one FB\_Picomag for the flow meter. Naturally, this is a Picomag from Endress+Hauser.

```auto
FUNCTION_BLOCK FB_Picomag EXTENDS FbIOL_Base
VAR_IN_OUT
	xResetTotalizer: BOOL;
END_VAR
VAR_OUTPUT
	rConductivity: REAL;
	rFlow: REAL;
	rTotalizer: REAL;
	rTemperature: REAL;
	xIOLinkOK: BOOL;
END_VAR
VAR
	RTrigReset: R_TRIG;
	bytesConv: U_BytesToReal;
	bResetWritten: BYTE;
END_VAR
SUPER^();

IF THIS^.Prop_xInDataValid THEN
	// Conductivity
	bytesConv.abBytes[3] := aDeviceInData[0];
	bytesConv.abBytes[2] := aDeviceInData[1];
	bytesConv.abBytes[1] := aDeviceInData[2];
	bytesConv.abBytes[0] := aDeviceInData[3];
	rConductivity := bytesConv.rValue;

	// Flow
	bytesConv.abBytes[3] := aDeviceInData[8];
	bytesConv.abBytes[2] := aDeviceInData[9];
	bytesConv.abBytes[1] := aDeviceInData[10];
	bytesConv.abBytes[0] := aDeviceInData[11];
	// Scaling by 60, as we apparently receive the value as liters/s.
	rFlow := bytesConv.rValue * 60.0;

	// Totalizer
	bytesConv.abBytes[3] := aDeviceInData[4];
	bytesConv.abBytes[2] := aDeviceInData[5];
	bytesConv.abBytes[1] := aDeviceInData[6];
	bytesConv.abBytes[0] := aDeviceInData[7];
	rTotalizer := bytesConv.rValue;
	
	// Temperature
	rTemperature := (INT_TO_REAL(aDeviceInData[12]) * 256.0 + INT_TO_REAL(aDeviceInData[13])) / 10.0;

	xIOLinkOK := TRUE;
	
	RTrigReset(CLK := xResetTotalizer);
	IF RTrigReset.Q THEN
		THIS^.IOL_Call_WriteWord(wIOL_Index := 362, bIOL_Subindex := 0, wValue := 1, bLen => bResetWritten);
		xResetTotalizer := FALSE;
	END_IF

	
ELSE
	xIOLinkOK := FALSE;
	
END_IF

```

Running as a separate task is this main program PRG\_IOLink:

```auto
PROGRAM PRG_IOLink
VAR
xExecuteMain: BOOL := TRUE;
xDoneConfig: BOOL;
xBusyConfig: BOOL;
xErrorConfig: BOOL;
oStatusConfig: FbResult;
aPort: ARRAY [1..4] OF typIOLinkPortConfigBasic;
aIOLPort: ARRAY[1..4] OF typIOL_Device;
aIOLDevice: ARRAY [1..4] OF typIOLinkDeviceInfo;
xEnableDiagnosis: BOOL := TRUE;
xResetDiag: BOOL;
aDiagBuffer: ARRAY[0..IOL_DIAG_BUFFER] OF typDiag;
aDiagTimeBuffer: ARRAY[0..IOL_DIAG_BUFFER] OF DATE_AND_TIME;

IOL_Config_1657: WagoAppIOLink.FbIOL_MasterConfiguration_1657;
currentDT: DATE_AND_TIME;
RTCResult: RTS_IEC_RESULT;
xDiagResult: BOOL;
n : INT;
emptyPipeDetected: BOOL;

// Picomag
PicomagAnPort1: FbIOL_PortData;
PicoMagObj: FB_Picomag;
bytesConv: U_BytesToReal;
pOutBuffer: ARRAY[0..2] OF BYTE;
pInBuffer: ARRAY[0..14] OF BYTE;

xTxTriggerPicomag: BOOL := FALSE;
xCommResetPicomag: BOOL:= FALSE;
xValidPicomag: BOOL;
xBusyPicomag : BOOL;
xErrorPicomag: BOOL;
udiRxBytesPicomag: UDINT;
bRefreshCounterPicomag: BYTE;
oStatusPicomag: FbResult;
xInit: BOOL := FALSE;

END_VAR

IF NOT xInit THEN
	xInit := TRUE;
	// At the start of the controller, we assume a full pipe. 
	// After all, "EMPTY PIPE" is an error that is reported to us or not.
	GVL_IO.Filterpumpe_LeitungVoll := TRUE;
END_IF

aPort[1].bRXSize := 15;
aPort[1].eIOL_PortMode := eIOL_PortMode.IOL_Sensor;
aPort[1].xFragmented := FALSE;

aPort[2].eIOL_PortMode := eIOL_PortMode.Deactivated;
aPort[3].eIOL_PortMode := eIOL_PortMode.Deactivated;
aPort[4].eIOL_PortMode := eIOL_PortMode.Deactivated;

currentDT := UDINT_TO_DT(SysTimeRtcGet(pResult := RTCResult));

IOL_Config_1657(
	xEnable := xExecuteMain,
	I_Port := IoConfig_Globals._750_1657_24,
	eModeStartUp := eMasterConfigModeStartUp.AutoConfig,
	aPort := aPort,
	xDone => xDoneConfig,
	xBusy => xBusyConfig,
	xError => xErrorConfig,
	oStatus => oStatusConfig,
	aIOL_Port => aIOLPort,
	aIOL_DeviceInfo => aIOLDevice,
	dtTime := currentDT,
);

xDiagResult := IOL_Config_1657.GetDiagnosisBuffer(
	xEnable := xEnableDiagnosis,
	xReset := xResetDiag,
	aDiagBuffer := aDiagBuffer,
	aDiagTimeBuffer := aDiagTimeBuffer);

emptyPipeDetected := FALSE;
FOR n := 0 TO IOL_DIAG_BUFFER DO
	IF NOT emptyPipeDetected AND aDiagBuffer[n].EventCode = 6158 THEN
		emptyPipeDetected := TRUE;
		IF aDiagBuffer[n].DiagQualifier.DiagMode = eDiagQualMode.MBX_DiagAppears THEN
			GVL_IO.Filterpumpe_LeitungVoll := FALSE;
		ELSE
			GVL_IO.Filterpumpe_LeitungVoll := TRUE;
		END_IF
		xResetDiag := TRUE;		
	END_IF
END_FOR

PicoMagObj(
	typIOL_Sensor := aIOLPort[1],
	typIOLinkDeviceInfo := aIOLDevice[1],
	oStatus => oStatusPicomag,
	xError => xErrorPicomag,
	xResetTotalizer := GVL_IO.Filterpumpe_ZaehlerReset_Ausgang,
	);
	

GVL_IO.Filterpumpe_Conductivity := PicoMagObj.rConductivity;
GVL_IO.Filterpumpe_Flow := PicoMagObj.rFlow;
GVL_IO.Filterpumpe_Totalizer := PicoMagObj.rTotalizer;
GVL_IO.Filterpumpe_Temperature := PicoMagObj.rTemperature;
GVL_IO.Filterpumpe_IOLinkOK := PicoMagObj.xIOLinkOK;

```

A special feature is that the “Empty Pipe” message does not come from the device itself but from the IO-Link diagnosis buffer. For example, the LED on the terminal also lights up red as soon as the Picomag reports an Empty Pipe.

---

<div class="post-metadata">

**Author:** ![GombasG](https://avatars.discourse-cdn.com/v4/letter/g/3d9bf3/32.png) [@GombasG](https://www.wago.community/u/GombasG)\
**Post date:** [June 17, 2026, 9:58am UTC](https://www.wago.community/t/io-link-klemme-750-1657-am-pfc200-nutzen/2602/6 "2026-06-17T09:58:16Z")

</div>

Thank you very much, I plan to use the same Flowmeters, just 4 of them, this will help me a lot!
