CANBus Layer 2 CFC Example in Codesys 3.5 SP19 wanted

Im really struggling to implement a simple Layer 2 Canbus connection in my project, to start with i only need to send and recieve one 11bit message.
I am running Codesys 3.5 SP19 and a 752-8303 Edge Controller with onboard CANbus port

I have tried following the very limited documentation online and other posts, but all appear to be missing details on how to trigger the functions.

I have most experience with CFC, but this is fairly limited.

As an alternative i have tried setting up the CANopen Manager and tried turning off as much of the higher layer funcionality as i can all i seem to get it errors

Does anyone have a sinple example of how to send and recieve a simple can message that i can then build on. The key thing is it works in a recent version of Codesys as all other examples i found online relate older versions or eCockpit

Hello, First you need to add the WAGO_CAN_Layer2_Device on the CANbus port of the 8303 (something like this:
image
)

Next you need to use the WagoAppCanLayer2.FbCanL2Open function block:

VAR
	_oCanLayer2_Open	: WagoAppCanLayer2.FbCanL2Open;
		_xEnable			: BOOL := TRUE;
		_udiBaudrate		: UDINT := 250000;
		_dwFlags			: DWORD := 0;
		_dwPara			: DWORD := 0;
		_xValid			: BOOL;
		_xBusy			: BOOL;
		_xError			: BOOL;
		_oStatus			: WagoAppCanLayer2.WagoSysErrorBase.FbResult;


	_oCanRx11BitFrame	: WagoAppCanLayer2.FbCanRx11BitFrame;
		_xEnable			: BOOL := TRUE; // enable function block
		_xBufferMode		: BOOL := FALSE; // False:get latest message, True: use internal buffer ->allows to receive even old messages
		_wCanId			: WORD; // CAN ID
		_xRxTrigger		: BOOL; // activate the receive functionality
		_xValid			: BOOL; // data received
		_xError			: BOOL; // error occured
		_xBusy			: BOOL; // waiting for Can message with wCanID or waiting for xRxTrigger
		_wCounter		: WORD; // total received messages by this function block
		_wFrames		: WORD; // messages in buffer
		_xRtrFrame		: BOOL; // RTR frame received
		_bRxNBytes		: BYTE; // amount of byte in message
		_aRxBuffer		: ARRAY [1..8] OF BYTE; // data of CAN message


	_oCanTx11BitFrame	: WagoAppCanLayer2.FbCanTx11BitFrame;
		_xEnable			: BOOL := TRUE; // enable function block
		_xBufferMode		: BOOL := FALSE; // False:get latest message, True: use internal buffer ->allows to receive even old messages
		_wCanId			: WORD; // CAN ID
		_xRtrFrame		: BOOL; // RTR frame received
		_aTxBuffer		: ARRAY [1..8] OF BYTE; // data of CAN message
		_bTxNBytes		: BYTE; // amount of byte in message
		_xTxTrigger		: BOOL; // activate the receive functionality
		_xValid			: BOOL; // data received
		_xError			: BOOL; // error occured
		_xBusy			: BOOL; // waiting for Can message with wCanID or waiting for xRxTrigger
		
END_VAR
_oCanLayer2_Open(
	xEnable		:= _xEnable, 
	I_Port		:= IoConfig_Globals.WAGO_CAN_Layer2_Device, 
	udiBaudrate	:= _udiBaudrate, 
	dwFlags		:= _dwFlags, 
	dwPara		:= _dwPara, 
	xValid		=> _xValid, 
	xBusy		=> _xBusy, 
	xError		=> _xError, 
	oStatus		=> _oStatus
);

IF (_xRxTrigger) THEN	(* If ReadFrame Trigger ... *)
	_oCanRx11BitFrame(
		xEnable		:= _xEnable, 
		I_Port		:= _oCanLayer2_Open.I_Port, 
		xBufferMode	:= _xBufferMode, 
		wCanId		:= _wCanId, 
		xRxTrigger	:= _xRxTrigger, 
		xValid		=> _xValid, 
		xError		=> _xError, 
		xBusy		=> _xBusy, 
		oStatus		=> oStatus, 
		wCounter		=> _wCounter, 
		wFrames		=> _wFrames, 
		xRtrFrame	=> _xRtrFrame, 
		bRxNBytes	=> _bRxNBytes, 
		aRxBuffer	=> _aRxBuffer
	);
	
	IF NOT(_xRxTrigger) THEN (* If ReadFrame Trigger reset by function block ... *)
		abData := _aRxBuffer;
	END_IF;
END_IF;

IF (_xTxTrigger) THEN	(* If WriteFrame Trigger ... *)
	_oCanTx11BitFrame(
		xEnable		:= _xEnable, 
		I_Port		:= _oCanLayer2_Open.I_Port, 
		wCanId		:= _wCanId, 
		xRtrFrame	:= _xRtrFrame, 
		aTxBuffer	:= abData, 
		bTxNBytes	:= bDataLength, 
		xTxTrigger	:= _xTxTrigger, 
		xValid		=> _xValid, 
		xError		=> _xError, 
		xBusy		=> _xBusy, 
		oStatus		=> 
	);
	
	IF NOT(_xTxTrigger) THEN (* If ReadFrame Trigger reset by function block ... *)
		_wCounter := _wCounter + 1;
	END_IF;
END_IF;

Hi Wagolcard,

When I followed your steps above, I ran into many errors:

          

[ERROR] CANTest: PLC_PRG [Device: PLC Logic: Application](Line 15 (Decl)): C0142: A local variable named ‘_xEnable’ is already defined in ‘PLC_PRG’
[ERROR] CANTest: PLC_PRG [Device: PLC Logic: Application](Line 19 (Decl)): C0142: A local variable named ‘_xValid’ is already defined in ‘PLC_PRG’

Compile complete – 25 errors, 0 warnings
Build complete – 25 errors, 0 warnings : No download possible

Please help to fix the issue. Thanks.

Did you install the WagoAppCanLayer2 library to your project?

If you have already used variables _xEnable and _xValid elsewhere in your project code, simply declare differently named variables and substitute those names for what you see in WagoIcard’s code.

abData is the variable placeholder for the data you want to transmit. Replace that with your own variable or declare it as a byte array to pass transmit data into the function block.

Indeed there is some miss because I copy paste from different part of my project, here is a fixed one:

PROGRAM prgCAN
VAR
	_oCanLayer2_Open		: WagoAppCanLayer2.FbCanL2Open;
		_xEnable_Open		: BOOL := TRUE;
		_udiBaudrate_Open	: UDINT := 250000;
		_dwFlags_Open		: DWORD := 0;
		_dwPara_Open		: DWORD := 0;
		_xValid_Open		: BOOL;
		_xBusy_Open			: BOOL;
		_xError_Open		: BOOL;
		_oStatus_Open		: WagoAppCanLayer2.WagoSysErrorBase.FbResult;
	
	_oCanRx11BitFrame		: WagoAppCanLayer2.FbCanRx11BitFrame;
		_xEnable_Rx11		: BOOL := TRUE; // enable function block
		_xBufferMode_Rx11	: BOOL := FALSE; // False:get latest message, True: use internal buffer ->allows to receive even old messages
		_wCanId_Rx11		: WORD; // CAN ID
		_xRxTrigger_Rx11	: BOOL; // activate the receive functionality
		_xValid_Rx11		: BOOL; // data received
		_xError_Rx11		: BOOL; // error occured
		_xBusy_Rx11			: BOOL; // waiting for Can message with wCanID or waiting for xRxTrigger
		_oStatus_Rx11		: WagoAppCanLayer2.WagoSysErrorBase.FbResult;
		_wCounter_Rx11		: WORD; // total received messages by this function block
		_wFrames_Rx11		: WORD; // messages in buffer
		_xRtrFrame_Rx11		: BOOL; // RTR frame received
		_bRxNBytes_Rx11		: BYTE; // amount of byte in message
		_aRxBuffer_Rx11		: ARRAY [1..8] OF BYTE; // data of CAN message
	
	_oCanTx11BitFrame		: WagoAppCanLayer2.FbCanTx11BitFrame;
		_xEnable_Tx11		: BOOL := TRUE; // enable function block
		_xBufferMode_Tx11	: BOOL := FALSE; // False:get latest message, True: use internal buffer ->allows to receive even old messages
		_wCanId_Tx11		: WORD; // CAN ID
		_xRtrFrame_Tx11		: BOOL; // RTR frame received
		_aTxBuffer_Tx11		: ARRAY [1..8] OF BYTE; // data of CAN message
		_bTxNBytes_Tx11		: BYTE; // amount of byte in message
		_xTxTrigger_Tx11	: BOOL; // activate the receive functionality
		_xValid_Tx11		: BOOL; // data received
		_xError_Tx11		: BOOL; // error occured
		_xBusy_Tx11			: BOOL; // waiting for Can message with wCanID or waiting for xRxTrigger
		_oStatus_Tx11		: WagoAppCanLayer2.WagoSysErrorBase.FbResult;
		_wCounter_Tx11		: WORD;
		
	abData_Rx11				: ARRAY [1..8] OF BYTE;
	bDataLength_Rx11		: BYTE;
	abData_Tx11				: ARRAY [1..8] OF BYTE;
	bDataLength_Tx11		: BYTE;
END_VAR
_oCanLayer2_Open(
	xEnable		:= _xEnable_Open, 
	I_Port		:= IoConfig_Globals.WAGO_CAN_Layer2_Device, 
	udiBaudrate	:= _udiBaudrate_Open, 
	dwFlags		:= _dwFlags_Open, 
	dwPara		:= _dwPara_Open, 
	xValid		=> _xValid_Open, 
	xBusy		=> _xBusy_Open, 
	xError		=> _xError_Open, 
	oStatus		=> _oStatus_Open
);

IF (_xRxTrigger_Rx11) THEN	(* If ReadFrame Trigger ... *)
	_oCanRx11BitFrame(
		xEnable		:= _xEnable_Rx11, 
		I_Port		:= _oCanLayer2_Open.I_Port, 
		xBufferMode	:= _xBufferMode_Rx11, 
		wCanId		:= _wCanId_Rx11, 
		xRxTrigger	:= _xRxTrigger_Rx11, 
		xValid		=> _xValid_Rx11, 
		xError		=> _xError_Rx11, 
		xBusy		=> _xBusy_Rx11, 
		oStatus		=> _oStatus_Rx11, 
		wCounter	=> _wCounter_Rx11, 
		wFrames		=> _wFrames_Rx11, 
		xRtrFrame	=> _xRtrFrame_Rx11, 
		bRxNBytes	=> _bRxNBytes_Rx11, 
		aRxBuffer	=> _aRxBuffer_Rx11
	);
	
	IF NOT(_xRxTrigger_Rx11) THEN (* If ReadFrame Trigger reset by function block ... *)
		abData_Rx11 := _aRxBuffer_Rx11;
		bDataLength_Rx11 := _bRxNBytes_Rx11;
	END_IF;
END_IF;

IF (_xTxTrigger_Tx11) THEN	(* If WriteFrame Trigger ... *)
	_aTxBuffer_Tx11 := abData_Tx11;
	_bTxNBytes_Tx11 := bDataLength_Tx11;
	_oCanTx11BitFrame(
		xEnable		:= _xEnable_Tx11, 
		I_Port		:= _oCanLayer2_Open.I_Port, 
		wCanId		:= _wCanId_Tx11, 
		xRtrFrame	:= _xRtrFrame_Tx11, 
		aTxBuffer	:= _aTxBuffer_Tx11, 
		bTxNBytes	:= _bTxNBytes_Tx11, 
		xTxTrigger	:= _xTxTrigger_Tx11, 
		xValid		=> _xValid_Tx11, 
		xError		=> _xError_Tx11, 
		xBusy		=> _xBusy_Tx11, 
		oStatus		=> _oStatus_Tx11
	);
	
	IF NOT(_xTxTrigger_Tx11) THEN (* If ReadFrame Trigger reset by function block ... *)
		_wCounter_Tx11 := _wCounter_Tx11 + 1;
	END_IF;
END_IF;

Thanks, it is working now.