Skip to content
Menu
PLC-BMS
  • Home
  • Tools & Technology
  • Blog
PLC-BMS

Periodic SDO Transfers using Function Blocks

Posted on July 30, 2025

Automatic tools are great to get started receiving and setting SDO for slave devices.

But the need for finer control than what is possible with PLC manufacturers’ configuration tools, like EPEC Multitool, can arise for various reasons:

  • You want more flexibility on the timing of the requests
  • You want to test custom SDOs of your own
  • You want to debug which particular SDO makes the slave device bug.

This is where a finer understanding of the EPEC CAN Open library for Codesys comes in handy.

In this white paper, we will understand EPEC’s CANopenCSDOTransfer Function Block, the role of the arguments in the CAN Open stack, and how to organize a Function Block (FB) written in Structure Text IEC 61131-3 format.

Function Blocks

Before we go into the details on data, I think it is easy to get confused when using Function Blocks. Some developers will always default to create a Program (PRG) ST file.

A way to see it is that function blocks are structures not only containing data, but also executable code. You set the the data used by the function block like a structure, and you run the code as if calling a PRG.

This means they have for limitation:

  • Two function blocks do not know of the existence of each other implicitly: the data of the function block is not shared between implementations of the function blocks.
  • Function blocks can access global variables (like the static implementation of a CAN network)
  • You can call function blocks like any program, only this program is also a variable and must be declared in the variable section.

Using EPEC’s CANopenCSDOTransfer function block

To handle SDO transfers in relation with the CANOpen network, EPEC has implemented their own function block to allocate data and structure the temporary and output values which can be useful for the user.

This is why we add an instance of this FB in our code:

VAR
    (* Function block to use the EPEC driver *)
    fbCommand : CANopenCSDOTransfer;
END_VAR

This allocates and creates the interface with the driver to:

  • Check the CAN Channel for the channel’s status
  • Update the status variables of the command
  • If all is possible, effectively receive or send data on the bus.

Checking the command’s status

Using this fbCommand object, we can now start the transfer, set its parameters and check if there are errors in the transfer’s execution using its output values:

  1. fbCommand.o_Ready
    The command will be sent only when the transfer data has been updated as a result of the request. The other status are not relevant before the command is ready for transfer
  2. fbCommand.o_State
    The states 0 and 3 are states indicating the command has been handled, maybe unsuccessfully.
  3. fbCommand.o_Error
    If the command is not handled properly, an error code will be sent back, different to CANopenCSDOErrorSuccess.

Waiting, checking, and restarting the transfer for every SDO will clutter our code, and will mix driver level feedback with main execution loops. Hence the need to encapsulate this low-level function block in an easy to use function block running its own operational state machine.

Designing the SDOTransfer Function Block

The objective of this object will be to make it possible to initialize, transfer, and return the transfer’s health without having to deal with timing, driver or other low-level calls at the caller’s level.

The easiest way to handle this is to instantiate the driver’s function block, and create a transfer state machine:

Once the state machine is implemented, we can instantiate and call SDOTransfer function blocks for as many SDO, with the timing required by the application, simply from modules communicating with the CANOpen network without having to worry about the implementation details.

And if there is a need of a bug fix or a new feature, an update of the FB will be replicated automatically to all of the instances.

Code

Code sample for this function block and a simple Main implementation are available on Github:

https://github.com/AlphaPaul/SimpleSDO_ST

The EXP files can be opened with a text editor, or with Codesys 2.3. Please check it out and feedback on what you feel is missing, what can be updated, or simply if this example has been of value to your project.

  • CANOpen
  • Codesys
  • EPEC
  • IEC 61131-3
  • PLC
  • Programming

Leave a Reply Cancel reply

Your email address will not be published. Required fields are marked *

  • October 1, 2025 by Paul First Project with IFM CR403S : Blinky This post is an illustrated guide / tutorial to setup CR403S Codesys 3.5 projects with service (debug) communication. It can be used by beginners in both Codesys 3.5 as...
  • July 30, 2025 by Paul Periodic SDO Transfers using Function Blocks Automatic tools are great to get started receiving and setting SDO for slave devices. But the need for finer control than what is possible with PLC manufacturers' configuration tools,...
  • July 25, 2025 by Paul Coming Soon Content will be updated soon, stay tuned for tips on IEC 61131-3 Structured Text (ST) development, integrating legacy electronics, monitoring and evaluating the safety and compliance of battery systems.

PLC-BMS

Paul Innovation and Electronics B.V.
Enschede, the Netherlands

Kvk: 95592350

BTW/VAT : NL867195915B01

About

We are a team of two, planning on growing rapidly.

Paul is a passionate electrical engineer, with 15 years of experience developing systems for customers.

Soizic is a dynamic project manager with 9 years experience in a wide range of sectors.

Contact

info@paulinnov.com

  • Paul
  • Soizic
©2026 PLC-BMS | WordPress Theme by Superb Themes