[go: up one dir, main page]

0% found this document useful (0 votes)
51 views123 pages

01 Manual MotionCode 240703

Uploaded by

YOUSSEF AKID
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
51 views123 pages

01 Manual MotionCode 240703

Uploaded by

YOUSSEF AKID
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 123

Documentation for Motioncode

Table of contents

1. MotionCode 3

1.1 Overview 3

1.2 Set Up 4

1.3 Usage 6

1.4 Release Notes 108

1.5 FAQ 109

Version 03-07-2024 Motioncode documentation Page 2 / 123


1. MotionCode

1.1 Overview
With the Motor Control Platform (MCP), Dunkermotoren offers the possibility of creating MotionCodes. These are
autonomously running programs in the motor that a programmer writes for individual customer applications. All Dunker
parameters as well as calculation functions and logical concatenations can be used. You can program sequence loops or
send commands to other devices and process feedback from devices. The development environment is Eclipse and
programming is done using the programming language "C". With the help of a template, entering the programming world
is made easier and you can start directly with programming in Eclipse after setting up the software package. After
completion of a Code, it can be built and loaded into the motor via an upgrader. Since some software components are
required, a preconfigured Eclipse package is provided.

Version 03-07-2024 Motioncode documentation Page 3 / 123


1.2 Set Up

1.2.1 Requirements

MotionCode IDE Package

The MotionCode IDE package provides an Eclipse-based development environment for MotionCodes. All necessary
components are already installed. The package is provided as an .zip file and only needs to be unpacked. No
administrator rights are necessary.

System Requirements

64-bit Windows operating system ( 7/8/10 )


Internet access would be an advantage
For the IDE package, 1500 MB memory should be available.

Download

Get MotionCode from Webside

www.dunkermotoren.com » Downloads » Software » MotionCode

Hint

If the ZIP file can't be unpacked, the contents must be allowed via "Right click » Properties » General » Security".

Version 03-07-2024 Motioncode documentation Page 4 / 123


Additional Downloads

DriveAssistant5

PC parameterizing program, to parameterize all dPro and dMove variants with internal or external electronics.

Download

KnowledgeBase

chm HTML-help file: Pin assignment of standard motors, examples, parameter description/ object directory

Download

Manual

manuals and function & connection guides.

Download

Version 03-07-2024 Motioncode documentation Page 5 / 123


1.3 Usage

1.3.1 MotionCode IDE

Run IDE

To start the MotionCode IDE, navigate to the unpacked folder „\MotionCode_IDE\“ and start the „MotionCodeIDE.exe“-
file.

Hint

The "MotionCodeIDE_Updater" checks automatically after each start if an update of the Dunkermotoren Library is
available.

Version 03-07-2024 Motioncode documentation Page 6 / 123


Launcher

After starting the IDE first time, the following window appears:

The storage location of Workspace must be specified here. For all further information on Workspace see „Workspace“.

In the next step you will be redirected to the intro page. Closing it takes you to the standard desktop.

Here you will see the typical Eclipse editing screen. In this menu you can edit the different projects in the respective
workspace.There are basically six different sections here

Version 03-07-2024 Motioncode documentation Page 7 / 123


6

1 5 4

Text is not SVG - cannot display

1. Project Explorer
The various projects and the files they contain are displayed here. Right-click on the project folder to delete,
open, close, etc. the project. Several projects can be opened at the same time.
2. Device Selection
Motors can be connected directly to the IDE for programming and debugging purpose.
3. Console
Here you can see the current action and the progress when performing various functions. When "building" a
project, possible error messages are displayed here.
4. Functions/Tasks
In this window, all available functions of the currently opened module are displayed.
5. Source Code
Here, you can find the source code of your current project. Changes in this one are made exclusively here.
6. Menu Bar
In the menu bar of the workspace window provides quick access to commonly used features and functions of
the IDE.

Version 03-07-2024 Motioncode documentation Page 8 / 123


1.3.2 Project

Workspace

A workspace path is specified when Eclipse is started. The Workspace is intended as a local working folder,which every
programmer keeps for himself and in which he can create and manage projects. Here, Eclipse stores local settings (e.g.
views and size of subwindows) and links to projects. A newly created project (see Create Project) is also stored in the
workspace. The projects can therefore be located at file level in the workspace, but they do not have to. Thus it is
possible to link projects from a remote directory to its workspace via an import (see Import Project). The workspace is
separate from the Eclipse installation. Multiple workspaces can be opened simultaneously using multiple instances of the
same Eclipse installation. Eclipse remembers the last used workspaces and suggests them in a dropdown list at startup.

Import Project

Existing projects are imported into the workspace via File -> Import -> General -> Existing Projects into Workspace.
Alternatively, an archived project can also be imported (see following figure).

Version 03-07-2024 Motioncode documentation Page 9 / 123


A project is only visible in the Project Explorer (see the following figure), when it has been imported, even if it is already
physically in the workspace.

Explorer View Project View

Info

MotionCode projects usually consist of "inc" and "src" directories and project files ".cproject" and ".project", which
hold the source code together and contain build instructions. The subfolder "dProMotionCode_Debug" in the figure
above is the output directory for the compiled MotionCode. This one is not necessarily included in imported
projects, since it can be recreated at any time. For the complete reproduction of a project only the source files (inc/
src) and project files (.cproject/.project) have to be archived.

Version 03-07-2024 Motioncode documentation Page 10 / 123


Export Project

If a project need to be transferred or its storage location changed (e.g. for new projects that are initially all located in the
workspace), the Eclipse export function is recommended. It can be accessed with the project selected via File -> Export
or in the Project Explorer contextmenu.

Export Contextmenu

Export Wizard

Then there is the possibility to create an archive


(e.g. *.zip) or File System under General. Both

Version 03-07-2024 Motioncode documentation Page 11 / 123


pack the project with the necessary source and project files into a handy archive file.

Export Settings

In the following dialog, the settings should be


made as shown.

Version 03-07-2024 Motioncode documentation Page 12 / 123


Create Project

New MotionCode projects are created via File -> New -> MotionCode Template... or in the context menu of the Project
Explorer over the Project Wizard. A new project is created with template code and first physically stored in the workspace
directory.

New Project

Project Wizard

Version 03-07-2024 Motioncode documentation Page 13 / 123


Project Properties

The project properties can be accessed via File -> Properties (1) for the selected project or in its context menu. By
default, there are already different "Build Configurations" for each project, which can then be selected in the upper area
by dropdown.

1.

File -> Properties

Version 03-07-2024 Motioncode documentation Page 14 / 123


Info

Some settings can also be used for [All configurations]. So special care should be taken with the currently selected
configuration!

Build Configurations

A build configuration contains a set of compiler and linker settings that are not relevant to the default user. The user
should only select for which electronics type he writes the MotionCode: dMoveCO, dProCO, dProEC or dProPN. A quick
selection of the Build Configuration is also possible in the main menu band of Eclipse via the pointer symbol:

MotionCodeFunctionLibrary Version

Dunkermotoren delivers together with the IDE a functionlibrary which offers some useful functions. The build variable
MOTIONCODE_FUNCTIONLIBRARY_VERSION can be used to specify the version to be used. Which
MotionCodeFunctionLibrary versions are selectable can be found in the following subfolder in the installation path:(Install)
\MotionCode_IDE\dunkermotoren\MotionCodeLibrary\MotionCodeFunctionLibrary

Version 03-07-2024 Motioncode documentation Page 15 / 123


Details about the included functions can be found in the Software Documentation chapter at the end of this document.

MotionCodeLibrary Version

The MotionCodeLibrary is the interface between MotionCode and the motor firmware.

In principle, the motor firmware is downward compatible with the MotionCode library: A MotionCode created with the help
of a MotionCodeLibrary of a certain version is compatible and executable with a motor firmware of the same or higher
version. If the extended functionalities of a higher version motor firmware are to be used, however, you must jump to the
corresponding MotionCode-Library version in the MotionCode project. This can beconfigured with the build variable
MOTIONCODE_LIBRARY_VERSION . Please note the following:

1. A MotionCodeLibrary version is not available for every version of the motor firmware. A new MotionCode-Library
version is only created if new parameters have been added to the firmware.
2. the exact notation of the „Value“ of the build variable must be followed. The build variable is used to assemble a
path string that points to the corresponding library. If the spelling is not correct or points to a version that is not
supported in the MotionCode IDE, then there is an error in the build process.

Which MotionCodeLibrary versions are selectable can be found in the following subfolder in the installation path: (Install)
\MotionCode_IDE\dunkermotoren\MotionCodeLibrary

New versions are added automatically via the updater

Version 03-07-2024 Motioncode documentation Page 16 / 123


The firmware version of the motor can be read out with DriveAssistant 5 (1)

1.

MotionCodeLibrary Variant

The build variable MOTIONCODE_LIBRARY_VARIANT can currently take the values dProCO, dProEC, dProPN or dMoveCO
and is set in the four default build configurations. There is usually no need for the user to make any changes here.

Material Number And Index Of The MotionCode

The build variables MOTIONCODE_MATERIALNUMBER and MOTIONCODE_MATERIALINDEX are only necessary for internal
purposes of Dunkermotoren. The entered values will be inserted into the MotionCode so that they can later be read out
via the corresponding communication objects listed in the following table.

Communication object Parameter Data type Corresponds to Build Variable


[Index.Subindex] (hex)

402E.08h MotionCode material number UInt64 MOTIONCODE_MATERIALNUMBER

402E.09h MotionCode material index UInt16 MOTIONCODE_MATERIALINDEX

MotionCode Version, Variant And Name

The MotionCode version and variant are not to be confused with the MotionCodeLibrary version and variant. This is a
versioning that the creator of the MotionCode can freely use for himself. Version, variant in integer format and also a
variant name in string format are defined as build variables in the Eclipse environment. The information entered here can
later be read out via the communication objects listed in the following table.

Communication object Description Data type Corresponds to Build Variable


[Index.Subindex] (hex)

5000.01h MotionCode variant UInt32 MOTIONCODE_VARIANT

5000.02h MotionCode variant name String MOTIONCODE_VARIANT_NAME

5000.03h MotionCode version String MOTIONCODE_VERSION

Version 03-07-2024 Motioncode documentation Page 17 / 123


Info

Since this information is stored in the source code and not in the project settings and individual build configurations,
it is adopted for each build configuration (e.g.dProCO and dMoveCO).

Build Process and Output File

The build process is triggered by the hammer icon in the main menu band for the desired configuration.

MCPDownloadCreator.exe

Shortly before the end, the following "MCPDownload-Creator.exe" window appears, which must be acknowledged (either
by any keystroke or terminating on X).

Output Project Explorer

Version 03-07-2024 Motioncode documentation Page 18 / 123


Afterwards "MotionCodeUpgrade.bin" will be moved to the output folder of the project "dProCOMotionCode_Debug". If
this is not visible, an update may be necessary (Select + F5 ). This is the binary file of the Motion Code that can be
transferred to the motor.

Note

It is not to be confused with "MotionCode.bin"!

Version 03-07-2024 Motioncode documentation Page 19 / 123


There are three ways to load the application into the Drive.

Upgrader.exe

The appropriate upgrader for the selected build configuration (e.g. dMoveCO or dProPN) is automatically created in the
"MCPUpgrader" subfolder.

-> see MCP Upgrader

DriveAssistant 5

Using DriveAssistant 5 Upgrader Plugin

-> see DriveAssistant

Direct from IDE

It's also possible to use the upgragder Functionality from the IDE

-> see IDE Upgrade

Version 03-07-2024 Motioncode documentation Page 20 / 123


1.3.3 Programming the Hardware
After the build process, the binary file will be created, which can be transferred to the motor

Connection to the Motor

A distinction is made here between dMoveCO, dProCO, dProEC and dProPN. However, the same tools are used for all of
them. For all variants, the Upgrader or DA5 is used to connect to the motor.

The connection is established on the left section in the DA5/MCP Upgrader and differs in CANopen, EtherCAT and
Industrial-Ethernet(PN):

dMoveCO / dProCO

The connection to the motor must be established via the miCAN stick and the USB interface on the PC.

Version 03-07-2024 Motioncode documentation Page 21 / 123


dProEC

The connection to the motor must be established via a PC Ethernet interface and the IN port of the EtherCAT interface of
the motor. For some users it happens that the connection only works if the Ethernet interface was already connected to
the PC when the PC was booted.

Version 03-07-2024 Motioncode documentation Page 22 / 123


dProPN

The connection to the motor must be established via a PC Ethernet interface and any Profinet port of the motor. It is
important that the PC Ethernet interface has an ipv4 IP address in the appropriate address range of the motor. If the
motor has not received an IP address from a Profinet controller, the DA5/Upgrader automatically assigns a suitable IP
address.

Version 03-07-2024 Motioncode documentation Page 23 / 123


Link To MotionCode IDE

The MotionCode IDE offers the possibility to link to DriveAssistant 5. With this functionality its possible to download
MotionCode direct from IDE or using the Debugging feature.

Version 03-07-2024 Motioncode documentation Page 24 / 123


1. Start GDB Host (DriveAssistant5)
Navigate to Tools -> GDB Host -> Start GDB Host
Select a Port for the Host (Client side will need same Port)
Save

Start GDB Host

Select Port

2. Start GDB Client (MotionCodeIDE)


Navigate to GDB Client -> Start GDB Client
Select a Port for the Client (use Same Port like set before on Host side)
Save

Start GDB Client

Select Port

Version 03-07-2024 Motioncode documentation Page 25 / 123


Version 03-07-2024 Motioncode documentation Page 26 / 123
3. Connect to DriveAssistant 5
Click in the Device Selection Window from IDE
Afterwards the Connection should be etablished and shown in the Device Selection Window
Connect to DriveAssistant Connection Established

Info

It's possible to setup the Autostart function on Client and Host side. In this case GDB Host will startup with
DriveAssistant 5 and the Client with the MotionCodeIDE

Version 03-07-2024 Motioncode documentation Page 27 / 123


MCP Upgrader

The upgrader can be found in the respective project folder.

For example:

…\workspace\MyMotionCode\dProCOMotionCode_Debug\MCPUpgrader

This is automatically created suitable for the selected Build Configuration (e.g. dMoveCO or dProPN). Basically there are
two variants:

1. CAN based Build Configurations: dMoveCO and dProCO. -> These use directly the output file
"MotionCodeUpgrade.bin"
2. Ethernet based Build Configurations: dProEC and dProPN -> For these the output file "MotionCodeUpgrade.bin"
is processed again to "FWUPDATE.ZIP".

An upgrade package consists of the following files:

+ the corresponding MotionCodeUpgrade.bin or FWUPDATE.ZIP file.

By running Upgrader.exe the following interface opens and the upgrade can be started:

Version 03-07-2024 Motioncode documentation Page 28 / 123


The message "Upgrade successful" must appear after the procedure has been completed.

In case of possible errors in the consistency check, one or more numbers from the upgrader.exe.config file do not match
those of the motor.

DriveAssistant 5 Upgrader Feature

To use the toolchain upgrader, Drive Assistant 5 must be installed.

Version 03-07-2024 Motioncode documentation Page 29 / 123


Info

Only the DA5 or the MCP Upgrader can be opened. Parallel operation is not possible. This means that when
changing from Upgrader to DA5, the Upgrader must first be closed and vice versa.

Get DriveAssistant from Webside

Available free of charge: www.dunkermotoren.com » Downloads » Software »


Tools

To upload the MotionCode navigate to the Upgrader in the basic functions. Use the button to open the the upgrader
configuration from respective project folder.

For example:

…\workspace\MyMotionCode\dProCOMotionCode_Debug\MCPUpgrader\Upgrader.exe.config

By using the upgrader configuration the same files and values will be taken like using the MCP Upgrader.

Other Buttons:

-> Add single file to list (MotionCodeUpgrade.bin / Parameterlist.xml)


-> Remove single file from list
-> Clear complete list

IDE Upgrade

To start the Upgrade from the IDE a connection to the Motor has to be etablished (-> see Connection to the Motor)

The Upgrader can be started now over the Button in the main menu bar.

The path to the Upgrader will be preselected from the IDE. Taking the selected Project with it's active Build
Configurations.

For example:

…\workspace\MyMotionCode\dProCOMotionCode_Debug\MCPUpgrader

Version 03-07-2024 Motioncode documentation Page 30 / 123


With click on the Start button the selected Drive will be upgraded over the toolchain upgrader from DriveAssistant 5 in
background. The Progress is shown within this Window or acsessable in DriveAssistant 5.

Version 03-07-2024 Motioncode documentation Page 31 / 123


1.3.4 Template Overview and state machine
The template, which is generated via the "New MotionCodeProject" wizard, offers the programmer several predefined
functions and links in order to be able to implement a customer-specific application quickly and easily. The template
consists of several modules.

Folder Structure

Template Folder Structure:

MyMotionCode
|
├─ inc
│ ├─ MotionParameter.h
│ └─ ProgramSpecificFunctions.h
├─ src
│ ├─ MotionCode.c
│ ├─ MotionParameter.c
│ └─ ProgramSpecificFunctions.c
├─ Debug.xml
├─ DA5_Skript_MotionCodeDebug_2.00.py
└─ Default_Init.xml

Overview of files, modules and functions

The following descriptions only deal with the module contents that are necessary and important for the programmer. All
other functions must not be edited or changedby the user!

Version 03-07-2024 Motioncode documentation Page 32 / 123


The following modules and functions are available, which may be edited:

Object Description

MotionCode.c

motionCode_notification Here the behavior for events (NotificationTypes) is defined.

motionCode_init Storable MotionParameters are initialized here.

motionCode_main The actual MotionCode is defined here. This function is called and executed by the firmware.

bootupRoutine This function is called first in motionCode_main() after switching on the motor.

state machine (multiple) The state machine consists of several functions/states and is called in motionCode_main()

MotionParameter.c

setStorableDefaultValues The start values of the storable motion parameters are defined here when the motor is switched
on.

The start values of the motion parameters that cannot be saved are defined here when the
setNotStorableDefaultValues motor is switched on.

motionCode_odGetParameter Here MotionParameters are made readable from outside via CAN/PN/EC.

motionCode_odSetParameter Here motion parameters are made writable from outside via CAN/PN/EC.

MotionParameter.h

TagsForMyCommand Here names are assigned to the values of myCommand to make the MotionCode more
readable.

TagsForDebugProgramState Here names are assigned to the values of debugProgramState to make the MotionCode more
readable.

TagsForMyStatus Here names are assigned to the values of myStatus to make the MotionCode more readable.

motion_parameter_t The MotionParameters are declared here.

ProgramSpecificFunctions.c Here you can declare and define your own functions to make MotionCode.c clearer.
ProgramSpecificFunctions.h

Debug.xml This parameter list can be imported into DA5 and contains all motion parameters predefined in
the template

Default_CustomerSetting.xml This parameter list can be used to extend the upgrader to set adjustable variables before the
download.

Default_Init.xml This parameter list can be used to save it with the Upgrader as a parameter set on the drive.
For example, to initialize a CAN-PDO mapping.

DA5_Skript_MotionCodeDebug_2.00.py With this DA5 script the MotionParameters myCommand, myStatus and debugProgramState
are read cyclically and instead of the numerical values the names defined in MotionParameter.h
are output.

These are system functions which must not be deleted.Otherwise no MotionCode can be compiled.

For detailed information about the individual components and functions of the template, please refer to chapter Software
Dokumentation

Functionality of the state machine

The model of the state machine is often used for sequence programs. For this the template provides the function
stateFunction of the type stateMachine. It is already declared and can be used.

Version 03-07-2024 Motioncode documentation Page 33 / 123


Module: MotionCode.c

/**---------------- Private typedefs ------------------------------------------*/


typedef void (*stateMachine) (void); // Type definition "stateMachine"

/**---------------- Private variables & constants -----------------------------*/


static stateMachine stateFunction; // Generate stateFunction from type stateMachine

The stateMachine type is declared as a pointer, so when stateFunction() is called, it calls the function it is currently
pointing to. The assignment to which function stateFunction() points to is implemented as follows:

stateFunction = &stateControl; // Define stateControl as next state

This causes that the function stateControl() will be executed the next time stateFunction() is called.

Module: MotionCode.c
Function: motionCode_main()

In the function motionCode_main() the actually executed MotionCode is defined. In the template the cyclic call of the
state machine is already predefined:

187 /**---------------- Public module function definitions ------------------------*/


/*
188 *******************************************************************************
189 * Description:
* This is the 'MotionCode main function' executed by the motor firmware.
190 * --> It defines the really running MotionCode
191 * --> DO NOT REMOVE OR RENAME
*******************************************************************************
192 */
193 void motionCode_main(void* pd)
{
194 if(firstTimeExecuted == true) // If
195 MotionCode is executed the first time ..
{
196 while(true) // .. do
197 not execute the MotionCode ..
{
198
199 motionCodeFunctionLib_checkMotionParameterStoreCmdExtended(motionParameter.motionParameterStoreCmd);
just check motionParameterStoreCmd
200 }
201 }
202 else // Else (If
203 MotionCode is not executed the first time) ..
{
204 bootupRoutine(); // .. call
205 bootup routine
stateFunction = &stateControl; // .. set
206 stateControl as first state
207
208 while(true) // .. while
209 MotionCode is running ..
{
210
211 motionCodeFunctionLib_checkMotionParameterStoreCmdExtended(motionParameter.motionParameterStoreCmd);
check motionParameterStoreCmd
212 stateControl(); // .. ..
213 call state Control
stateFunction(); // .. ..
214 call state machine
215 }
}
216 }
217

The function stateControl() and the stateFunction() are always called alternately. By calling the stateFunction() , the function to
which it points is executed, as already described. The function stateControl is there to define which state should be called next:

Version 03-07-2024 Motioncode documentation Page 34 / 123


Module: MotionCode.c
Function: stateControl()

By default, the digital inputs are read in at the beginning and checked whether an error message is present:

68 /*
*******************************************************************************
69 * Description:
70 * This function is called cyclic. It is the base of the running state machine.
* --> It analyzes the active myCommand and DEVICE_ErrorCode.
71 * --> If they change: Depending on them the next stateFunction is defined.
72 *******************************************************************************
*/
73 void stateControl(void)
74 {
motionParameter.myCommand = motionCodeFunctionLib_readDebouncedDigitalInputs(0xFF,
75 *motionParameter.debounceTime); // Read DigitalInputs into myCommand
76
static uint32_t oldMyCommand = C_Undefined; // Stored
77 internal variable to detect changes of myCommand
78
int16_t actualError = 0; // Local
79 variable to read DEVICE_ErrorCode
80 drive->readI16(DEVICE_ErrorCode, &actualError); // Read
Error Register
81
82 if(actualError != 0) // If an
error is existing ..
83 {
84 oldMyCommand = C_Undefined; // .. reset
oldMyCommand
85 stateFunction = &stateError; // .. go to
86 stateError
}
87
88
89

If an error message is present the stateError() is called next. If an error message is to be acknowledged within the MotionCode this must be
realized in stateError() . More about this at the end of this chapter. If myCommand is written externally via CAN/EC/PN and does not depend on
the digital inputs, line 78 must be removed or commented out. Then it is checked whether the value of the motion parameter myCommand has changed.
If yes, the next state is defined in a switch-case branch:

90 else if(motionParameter.myCommand != oldMyCommand) // If no


error and myCommand did change => define next state
91 {
92 oldMyCommand = motionParameter.myCommand; // ..
Overwrite old myCommand
93
94 switch(motionParameter.myCommand) // ..
Define next stateFunction depending on myCommand
95 {
96 case C_Stop: // .. If
command == C_Stop ..
97 stateFunction =
98 &stateStop; // .. .. go to stateStop
break;
99 case C_StartMoving: // .. If
100 command == C_StartMoving ..
stateFunction =
101 &stateStartMoving; // .. .. go to stateStartMoving
102 break;
default: // .. If
103 command is undefined ..
104 motionParameter.debugProgramState = D_StateUndefined; // .. ..
set StateUndefined for debugging
105 stateFunction =
106 &stateControl; // .. .. do not call any state
break;
107 }
108 }
}

Version 03-07-2024 Motioncode documentation Page 35 / 123


It is predefined that with command C_Stop the stateStop() is called. With command C_StartMoving the stateMoving() is called.
This branch must be adapted according to the desired function and the existing commands.The current stateFunction() is executed cyclically
until an error occurs or myCommand changes. If the current state should be called cyclically again and again, nothing else has to be done. If the current
state is to be called only once, the predefined stateNOP() must be declared as a new stateFunction at the end of the called state. If a step chain is
to be started, the next state to be executed must be declared as a new stateFunction at the end of the called state. If an error message occurs the
stateError() is called:

Module: MotionCode.c
Function: stateError()

110 /*
*******************************************************************************
111 * Description:
112 * This stateFunction is called if an error occurs (see DEVICE_ErrorCode).
* --> Defines the actions to be done if an error occurs
113 *******************************************************************************
114 */
void stateError(void)
115 {
116 motionParameter.debugProgramState = D_StateError; // Set
StateError for debugging
117
118 // TODO: Define actions to be done when Error occurs
119 if(motionParameter.myCommand == C_ClearError) // If
120 command == C_ClearError
{
121 drive->writeUi8(DEVICE_Command,
122 1); // .. clear error
}
123
124 int16_t actualError = 0; // Local
variable to read DEVICE_ErrorCode
125 drive->readI16(DEVICE_ErrorCode, &actualError); // Read
126 Error Register
if(actualError ==
127 0) // If error is cleared ..
128 {
motionParameter.myStatus = S_ErrorCleared; // .. set
129 myStatus S_ErrorCleared
130 }
else
131 {
132 motionParameter.myStatus = S_Error; // .. else
set myStatus S_Error
133 }
134 }
135
136
137
138

In the predefined state, stateError() is called cyclically and checked each time whether the command C_ClearError
is present. If yes the error is acknowledged and if this was successful the status S_ErrorCleared is output. Otherwise
the status S_Error is output . If no more error is present, the stateFunction in stateControl is automatically overwritten
according to the present command.

Version 03-07-2024 Motioncode documentation Page 36 / 123


1.3.5 Write MotionCode

Programming MotionCode

In this chapter, a first MotionCode is created step by step. During the four steps, all relevant details will be discussed step
by step. In addition, numerous examples are given of how various tasks can be solved. All code snippets shown are
based on the template version MotionCodeTemplate_V2.03. or newer.

Version 03-07-2024 Motioncode documentation Page 37 / 123


The First MotionCode - Step By Step

In the following it is shown how a MotionCode can be written step by step. This MotionCode performs a relative
positioning with each positive edge at IN0. The set position and set speed can be changed via motor objects via CAN/
EC/PN. In addition, there is a cycle counter that counts each relative positioning and is saved every tenth time.
Step 1: Creating the first move command

As described in the previous chapter, stateStop() and stateStartMoving() are already predefined in the state
machine. These are called with the commands C_Stop and C_StartMoving . These commands are predefined as
follows:

../inc/MotionParameter.h TagsForMyCommand

33 enum TagsForMyCommand
{
34 C_ClearError = 15, // Command
35 C_ClearError --> IN0=1 IN1=1 IN2=1 IN3=1 (IN4=0)
C_Stop = 0, // Command
36 C_Stop --> IN0=0 IN1=0 IN2=0 IN3=0 (IN4=0)
37 C_StartMoving = 1, // Command
C_StartMoving--> IN0=1 IN1=0 IN2=0 IN3=0 (IN4=0)
38 C_Undefined = 0xFF, // Mandatory!
39 Define value which cannot happen (for init of variable "oldMyCommand" in stateControl)
};

For example, if for C_StartMoving the IN1 should be used instead of IN0, its value would have to be defined to 2. With
all digital inputs equal to zero, the command C_Stop is executed and the stateStop() is called:

../inc/MotionCode.c stateStop()

152 /*
*******************************************************************************
153 * Description:
154 * This stateFunction is called if myCommand C_Stop is detected.
* --> It stops the motor.
155 *******************************************************************************
156 */
void stateStop(void)
157 {
158 motionParameter.debugProgramState = D_StateStop; // Set
StateStop for debugging
159
160 // TODO: Define actions to be done in this state
// drive->writeUi8(DEVICE_Command, 3); // CMD_Halt
161 --> Stop Motor
162
motionParameter.myStatus = S_Stopped; // Set
163 S_Stopped
164 }
165
166
167

Version 03-07-2024 Motioncode documentation Page 38 / 123


To actually trigger a stop, line 164 must be activated.To do this, the // characters can be removed manually. Alternatively,
you can select the line and use the key combination ( ⌃ Ctrl + 7 ). The stateStop() should then look like this:

../inc/MotionCode.c stateStop()

159 void stateStop(void)


{
160 motionParameter.debugProgramState = D_StateStop; // Set
161 StateStop for debugging
162 drive->writeUi8(DEVICE_Command,
163 3); // CMD_Halt --> Stop Motor
164 motionParameter.myStatus = S_Stopped; // Set
165 S_Stopped
}
166

With digital input IN1 equal to one, the command C_StartMoving is executed and the stateStartMoving() is called:

../src/MotionCode.c stateStartMoving() ->

168 /*
*******************************************************************************
169 * Description:
170 * This stateFunction is called if myCommand C_StartMoving is detected.
* --> It starts the motor.
171 *******************************************************************************
172 */
void stateStartMoving(void)
173 {
174 motionParameter.debugProgramState = D_StateStartMoving; // Set
StateStartMoving for debugging
175
176 // TODO: Define actions to be done in this state
// programSpecificFunctions_doRelPos(512, 2000); // Do
177 relative positioning on 512 increments with 2000 rpm
178
motionParameter.myStatus = S_Moving; // Set
179 S_Moving
180 }
181
182
183

168 /*
*******************************************************************************
169 * Description:
170 * This stateFunction is called if myCommand C_StartMoving is detected.
* --> It starts the motor.
171 *******************************************************************************
172 */
void stateStartMoving(void)
173 {
174 motionParameter.debugProgramState = D_StateStartMoving; // Set
StateStartMoving for debugging
175
176 // TODO: Define actions to be done in this state
programSpecificFunctions_doRelPos(512, 2000); // Do
177 relative positioning on 512 increments with 2000 rpm
178
motionParameter.myStatus = S_Moving; // Set
179 S_Moving
180 }
181
182
183

To actually execute a move command, this must still be inserted. For the fast start under ProgramSpecific-Functions.h
the function programSpecificFunctions_doRelPos() was predefined. Line 180 must therefore be activated. If you hover

Version 03-07-2024 Motioncode documentation Page 39 / 123


afterwards with the mouse over the function its declaration is faded in, using the key combination ( ⌃ Ctrl +
Left Button ) leads you direct to its definition.

The function is passed the values targetPositionRelative and targetVelocity. In this case a relative positioning by 512
increments with the speed 2000 rpm is started. You are welcome to adjust the values. To start the relative positioning only
once, the stateStartMoving() must be called only once. Otherwise the relative positioning would be repeated cyclically
and the motor would move on to infinity. Therefore at the end of the stateStartMoving() the stateNOP() must be
defined as the next state. The stateStartMoving() should then look like this:

../src/MotionCode.c stateStartMoving()

175 void stateStartMoving(void)


{
176 motionParameter.debugProgramState = D_StateStartMoving; // Set
177 StateStartMoving for debugging
178 programSpecificFunctions_doRelPos(512, 2000); // Do
179 relative positioning on 512 increments with 2000 rpm
180 motionParameter.myStatus = S_Moving; // Set
181 S_Moving
182 stateFunction = &stateNOP; // Do not
183 call this state again
}
184

Now the first own MotionCode can be compiled and played on the motor (see Build Process). The relative positioning can
then be started with a positive edge at IN0. With the Upgrader or DA5 it can also be checked via the status information
whether the positioning has been executed. In addition, it can be checked whether the digital input is really present, if the
movement should not have been executed:

Position Digital Inputs

Version 03-07-2024 Motioncode documentation Page 40 / 123


However, positioning can only be performed once. After that, the drive does not respond to the positioning command
again. This is because a stop command is executed in the stateStop() . The parameter description of the
DEVICE_Command can be taken what must be done to start again:

In this case we decide to deactivate the output stage after the stop. This is to be realized in the next step.
Step 2: Extend state machine

The template is structured in such a way that the stateStop() is called as soon as all digital inputs are deactivated.
Thereby a CMD_Halt is delivered and the motor stops. This is to be supplemented now in the second step in such a way

Version 03-07-2024 Motioncode documentation Page 41 / 123


that the motor output stage is deactivated, as soon as the motor stands still. The status S_Stopped is to be set only
when the output stage is deactivated. With the command C_Stop (all digital inputs 0) the stateStop() is called:

../src/MotionCode.c stateStop()

159 void stateStop(void)


{
160 motionParameter.debugProgramState = D_StateStop; // Set
161 StateStop for debugging
162 drive->writeUi8(DEVICE_Command,
163 3); // CMD_Halt --> Stop Motor
164 motionParameter.myStatus = S_Stopped; // Set
165 S_Stopped
}
166

After executing the DEVICE_Command "CMD_Halt", the program should now wait until the motor has stopped. Until then
the state S_Stopped must not be set. A new state stateWaitForStop() is created. For this the new function must be
declared first:

../src/MotionCode.c

44 /**---------------- Private function declarations -----------------------------*/


void bootupRoutine(void); // Once
45 executed after bootup
46 void stateControl(void); // Basis of
state machine: Defines next state
47 void stateError(void); // Executed
48 if error is existing
void stateNOP(void); // No
49 Operation
50 void stateStop(void); // Executed
if command C_Stop
51 void stateWaitForStop(void); // Executed
after C_Stop
void stateStartMoving(void); // Executed
if command C_StartMoving

In addition, the new state must be defined in the enum TagsForDebugProgramState . Here, the function name is taken,
adding a „D_“ infront and the first letter is capitalized:

../inc/MotionParameter.h TagsForDebugProgramState

56 /*
*******************************************************************************
57 * Description:
58 * Assign names to values of debugProgramState Debug variable
*******************************************************************************
59 */
60 enum TagsForDebugProgramState
{
61 D_StateUndefined = 0,
62 D_StateError = 1,
D_StateNOP = 10,
63 D_StateStop = 20,
64 D_StateWaitForStop = 21,
D_StateStartMoving = 30,
65 };
66
67
68
69
70

Version 03-07-2024 Motioncode documentation Page 42 / 123


Then the state can be defined:

../src/MotionCode.c stateWaitForStop()

176 void stateWaitForStop(void)


{
177 motionParameter.debugProgramState = D_StateWaitForStop; // Set
178 StateWaitForStop for debugging
}
179

In this state, it must first be determined whether the motor is still rotating. To do this, the status register is read in first. The
drive interface is used to access motor parameters. By entering "drive." a selection window opens with the functions of
this drive interface. A read function with the appropriate data type is required. The data type of the status register is taken
from the knowledgebase:

So the readUi32 function is needed. As first argument the object name of the motor parameter is given, in this case
DEVICE_StatusRegister . As second argument the address of the local variable is given, into which the current value of
the read object is to be written. This is done by the & - operator before the variable name:

../src/MotionCode.c stateWaitForStop()

180 uint32_t readStatusRegister = 0;


drive->readUi32(DEVICE_StatusRegister, &readStatusRegister); // Read
181 actual value of DEVICE_StatusRegister

Now it must be checked whether the status bit 4 STAT_Moving is inactive. For this, the corresponding status bit is filtered
out by an AND operation. In MotionCodeFunctionLib.h all status bits have already been defined in an enum with
names. Using the names instead of the numerical values makes the MotionCode more readable. The If statement could
look like this:

../src/MotionCode.c stateWaitForStop()

183 if((readStatusRegister & STAT_Moving) == 0) // If not


moving...
184 {
185 }

If this query is now true, the output stage is deactivated and the status S_Stopped is set. For the deactivation of the
output stage a write function of the drive interface is needed. The data type is again taken from the knowledgebase:

Version 03-07-2024 Motioncode documentation Page 43 / 123


So the writeUi8 function is needed. The first argument is the object name of the motor parameter, in this case
DEVICE_EnablePowerStage . The second argument is the value to be written, in this case 0. If the power stage is
deactivated the stateWaitForStop() must not be called again. So the stateNOP() can be specified as the next state.
The finished stateWaitForStop() then looks like this:

../src/MotionCode.c stateWaitForStop()

176 void stateWaitForStop(void)


{
177 motionParameter.debugProgramState = D_StateWaitForStop; // Set
178 StateWaitForStop for debugging
179 uint32_t readStatusRegister = 0;
180 drive->readUi32(DEVICE_StatusRegister, &readStatusRegister); // Read
actual value of DEVICE_StatusRegister
181
182 if((readStatusRegister & STAT_Moving) == 0) // If not
moving...
183 {
184 drive->writeUi32(DEVICE_EnablePowerStage,0); // ..
disable power stage
185 motionParameter.myStatus = S_Stopped; // .. set
186 S_Stopped
stateFunction = &stateNOP; // .. do
187 not call this state again. Next State
188 }
}
189

The stateStop() must be adjusted so that the stateWaitForStop() will be called. The setting of the state S_Stopped
is removed and instead the stateWaitForStop() is set as the next stateFunction:

../src/MotionCode.c stateStop()

160 void stateStop(void)


{
161 motionParameter.debugProgramState = D_StateStop; // Set
162 StateStop for debugging
163 drive->writeUi8(DEVICE_Command,
164 3); // CMD_Halt --> Stop Motor
165 stateFunction = &stateWaitForStop; // Next
166 state = stateWaitForStop
}
167

Now the output stage is deactivated after stopping and only then the status S_Stopped is set. The new version of the
MotionCode can now be compiled and downloaded on the motor. With this it should be possible to restart the relative
positioning with every positive edge at IN0.

Version 03-07-2024 Motioncode documentation Page 44 / 123


Step 3: The first MotionParameters

In the next step, two motion parameters are created in order to be able to change the velocity and the position of the
relative positioning with IN0 from outside (via CAN/EC/PN, e.g. by means of DA5). First the motion parameters
TargetVelocity and TargetPosition are defined. Then the default values are defined. Then they have to be made readable
and writeable from outside.

First the motion parameters are defined:

We decide to use non-storable motion parameters. That means, the start value when switching on the motor is defined
by the source code and cannot be overwritten later by the variable from outside. The two new non-storable motion
parameters are declared in the motionParameter structure:

../inc/MotionParameter.h motion_parameter

83 struct motion_parameter
{
84 /* storable motion parameter */
85 uint32_t* debounceTime; // MOTIONCODE_PARAMETER_UI32_04
5102.04h rws
86
87 /* not storable motion parameter */
int32_t targetVelocity; // MOTIONCODE_PARAMETER_I32_01
88 5101.01h rw
89 int32_t targetPosition; // MOTIONCODE_PARAMETER_I32_02
5101.02h rw
90 uint32_t myCommand; // MOTIONCODE_PARAMETER_UI32_01
91 5102.01h rw
uint32_t myStatus; // MOTIONCODE_PARAMETER_UI32_02
92 5102.02h r
93 uint32_t debugProgramState; // MOTIONCODE_PARAMETER_UI32_03
5102.03h r
94 int32_t debug1; // MOTIONCODE_PARAMETER_I32_40
95 5101.28h rw
int32_t debug2; // MOTIONCODE_PARAMETER_I32_41
96 5101.29h rw
97 int32_t debug3; // MOTIONCODE_PARAMETER_I32_42
5101.2Ah rw
98 int32_t debug4; // MOTIONCODE_PARAMETER_I32_43
99 5101.2Bh rw
int32_t debug5; // MOTIONCODE_PARAMETER_I32_44
100 5101.2Ch rw
101 int32_t debug6; // MOTIONCODE_PARAMETER_I32_45
5101.2Dh rw
102 int32_t debug7; // MOTIONCODE_PARAMETER_I32_46
103 5101.2Eh rw
int32_t debug8; // MOTIONCODE_PARAMETER_I32_47
104 5101.2Fh rw
int32_t debug9; // MOTIONCODE_PARAMETER_I32_48
5101.30h rw
int32_t motionParameterStoreCmd; // MOTIONCODE_PARAMETER_I32_50
5101.32h rw
};

At this point the corresponding MOTIONCODE_PARAMETER_XX_X, index, subindex and whether readable (r), writable
(w) and/or storable (s) should be specified as a comment after each MotionParameter. Then you have here a simple
overview which parameters are already assigned. In addition, you can hover over the motion parameter in the source
code at any time to see which parameter it is linked to:

Which MOTIONCODE_PARAMETER_XX_X are available and which index/subindex are linked to them can be taken from
the table in chapter MotionParameter

Version 03-07-2024 Motioncode documentation Page 45 / 123


Next, the default values of the motion parameters are defined, which they have when the motor is switched on. Even if the
default value should be 0, this must be defined. For this there is the predefined function setNotStorableDefaultValues().
This is called every time the motor is switched on during bootupRoutine() :

../src/MotionCode.c bootupRoutine()

61 void bootupRoutine(void)
{
62 drive->restoreExtended(0xFFFFFFFFu, 0xFFFFFFFFu, 0xFFFFFFFFu, 0xFFFFFFFFu); // restore
63 all storable motion parameters
setNotStorableDefaultValues(); // Set
64 default values of not storable MotionParameter
65
drive->writeUi8(DEVICE_Command, 1); // .. Clear
66 Error
67 }

By entering "motionParameter." a selection window opens with all already defined motion parameters:

../src/MotionParameter.c setNotStorableDefaultValues()

MotionParameters that cannot be saved behave like normal variables and can be set to the desired value:

../src/MotionParameter.c setNotStorableDefaultValues()

61 void setNotStorableDefaultValues(void)
{
62 motionParameter.targetVelocity = 2000; // Set
63 default targetVelocity
motionParameter.targetPosition = 512; // Set
64 default targetPosition
65 motionParameter.myCommand = C_Undefined; // Set
myCommand default value
66 motionParameter.debugProgramState = D_StateUndefined; // Set
debugProgramState default value

In order to make the motion parameters externally accessible, they must be assigned to the corresponding
MOTIONCODE_PARAMETER_XX_X motor objects and made readable and writable. To make the MotionParameters
readable from outside the Get function is needed:

This consists of a switch case branch. Each case assigns a MotionParameter to a MOTIONCODE_PARAMETER_XX_X.
Each MotionParameter that does not appear in the Get function is not externally readable. In this case it was defined

Version 03-07-2024 Motioncode documentation Page 46 / 123


before that the TargetVelocity is assigned to the MOTIONCODE_PARAMETER_I32_01 and the TargetPosition is assigned to
the MOTIONCODE_PARAMETER_I32_02 . This is now defined accordingly:

../src/MotionParameter.c motionCode_odGetParameter()

98 com_object_if_error_t motionCode_odGetParameter(void* const this,


com_object_if_variable_t* value)
99 {
100 com_object_if_error_t result = ERROR_NONE; // DO NOT
REMOVE - Initialization of motionCode_odGetParameter()
101
102 switch(PARAMETER)
{
103 /* int32_t */
104 case MOTIONCODE_PARAMETER_I32_01: // Assign
MOTIONCODE_PARAMETER_I32_01 ..
105 value->i32 = (motionParameter.targetVelocity); // .. to
106 motionParameter targetVelocity
break;
107 case MOTIONCODE_PARAMETER_I32_02: // Assign
108 MOTIONCODE_PARAMETER_I32_02 ..
value->i32 = (motionParameter.targetPosition); // .. to
109 motionParameter targetPosition
110 break;
case MOTIONCODE_PARAMETER_I32_40: // Assign
111 MOTIONCODE_PARAMETER_I32_40 ..

In order to make the MotionParameters writable from the outside, the Set function is required:

This also consists of a switch case branch. By each case a MOTIONCODE_PARAMETER_XX_X is assigned to a
MotionParameter. Each MotionParameter that does not appear in the Set function cannot be written externally. Here, too,
the two new MotionParameters are assigned to the corresponding objects:

../src/MotionParameter.c motionCode_odSetParameter()

191 com_object_if_error_t motionCode_odSetParameter(void* const this, com_object_if_variable_t


value)
192 {
193 com_object_if_error_t result = ERROR_NONE; // DO NOT
REMOVE - Initialization of motionCode_odSetParameter()
194 drive_lib_if_error_t writeError; // DO NOT
195 REMOVE - Initialization of motionCode_odSetParameter()
196 switch(PARAMETER)
197 {
/* int32_t */
198 case MOTIONCODE_PARAMETER_I32_01: // Assign
199 MOTIONCODE_PARAMETER_I32_01 ..
(motionParameter.targetVelocity) = value.i32; // .. to
200 motionParameter targetVelocity
201 break;
case MOTIONCODE_PARAMETER_I32_02: // Assign
202 MOTIONCODE_PARAMETER_I32_02 ..
203 (motionParameter.targetPosition) = value.i32; // .. to
motionParameter targetPosition
204 break;
205 case MOTIONCODE_PARAMETER_I32_40: // Assign
MOTIONCODE_PARAMETER_I32_40 ..

Version 03-07-2024 Motioncode documentation Page 47 / 123


So the two MotionParameters are now completely defined and initialized. Both are externally readable and writable, but
not storable. However, in order for them to fulfill the desired function, the stateStartMoving() must still be adapted
accordingly. The two MotionParameters are simply inserted instead of the hard-coded values:

../src/MotionCode.c stateStartMoving()

198 void stateStartMoving(void)


{
199 motionParameter.debugProgramState = D_StateStartMoving; // Set
200 StateStartMoving for debugging
201 programSpecificFunctions_doRelPos(motionParameter.targetPosition,
202 motionParameter.targetVelocity); // Do relative positioning on 512 increments with 2000 rpm
203 motionParameter.myStatus = S_Moving; // Set
204 S_Moving
stateFunction = &stateNOP; // Do not
205 call this state again
206 }

After the project has been built and loaded onto the motor, a relative positioning with 2000 rpm to 512 increments is
carried out when IN0 is set. The motion parameters can now be read out and written with the DA5. This means that the
setpoint speed and setpoint position can be changed at any time. The parameter list attached to the MotionCode
project can be imported with the "Import parameter set" function (1).

1.

Version 03-07-2024 Motioncode documentation Page 48 / 123


This contains all MotionCode parameters predefined by the template. The imported parameter list can be renamed and
moved by right-clicking (1).

1.

Version 03-07-2024 Motioncode documentation Page 49 / 123


Parametrization ...

By clicking on the new parameters can be added. Either the complete parameter name or only a part can be
entered:

The two setpoints should now be added:

Now any values can be written. The motor then makes the specified movement with each positive edge at IN0. After
switching the motor off and on, however, the values are reset again.
Step 4: The first storable MotionParameter

In the last step, a storable MotionParameter is created. A kind of simplified cycle counter is realized, which always counts
up when a relative positioning is started. After every tenth time the value is to be stored in the EEPROM. First the

Version 03-07-2024 Motioncode documentation Page 50 / 123


MotionParameter NrOfRelPositionings is defined. Then the default value is defined. Then it is still made readable from
outside and a fixed address is assigned. Finally, the logic of the cycle counter is programmed.

../src/MotionParameter.h motion_parameter

83 struct motion_parameter
{
84 /* storable motion parameter */
85 uint32_t*
debounceTime; // MOTIONCODE_PARAMETER_UI32_04 5102.04h rws
86 uint32_t*
87 nrOfRelPositionings; // MOTIONCODE_PARAMETER_UI32_05 5102.05h rs
88 /* not storable motion parameter */
89

Info

It must be noted that storable MotionParameters are declared as pointers, since they must have a fixed address!

The next step is to set the default value that the MotionParameter should get when the MotionCode is executed for the
first time. For this purpose the predefined function setStorableDefaultValues() is used.

../src/MotionParameter.c setStorableDefaultValues()

50 void setStorableDefaultValues(void)
{
51 *motionParameter.debounceTime = 10; // Set
52 debounceTime default value [ms]
*motionParameter.nrOfRelPositionings = 0; // Set
53 nrOfRelPositionings default value
54 }

Info

Since the parameter is declared as a pointer, a * operator must be used to assign a value!!

Version 03-07-2024 Motioncode documentation Page 51 / 123


The setStorableDefaultValues() function is called during the UPDATED_MOTION_CODE notification type. This is only
called during the first execution of the MotionCode. In the NotificationType the defined value is then stored by the drive
interface and its store function:

../src/MotionCode.c motionCode_notification()

269 * --> See MotionCode documentation for details.


* --> DO NOT REMOVE OR RENAME
270 *******************************************************************************
271 */
void motionCode_notification (motion_code_notification_type_t notificationType)
272 {
273 switch(notificationType) //
Determine witch notoficationType is true
274 {
275 case UPDATED_MOTION_CODE: //
UPDATED_MOTION_CODE is called when the MotionCode is executed the first time
276 setStorableDefaultValues(); // .. set
277 default values of storable MotionParameters
drive->storeExtended(0xFFFFFFFFu, 0xFFFFFFFFu, 0xFFFFFFFFu,
278 0xFFFFFFFFu); // .. store all storable MotionParameters
279 firstTimeExecuted = true; // .. set
firstTimeExecuted
280 break;
281 default:
break;
282 }
283 }
284
285

This ensures that the default values defined here can be overwritten later during runtime. During bootupRoutine() , the
last stored value of all storable MotionParameters is then restored each time the motor is switched on:

../src/MotionCode.c bootupRoutine()

61 void bootupRoutine(void)
{
62 drive->restoreExtended(0xFFFFFFFFu, 0xFFFFFFFFu, 0xFFFFFFFFu, 0xFFFFFFFFu); // restore
63 all storable motion parameters
setNotStorableDefaultValues(); // Set
64 default values of not storable MotionParameter
65
drive->writeUi8(DEVICE_Command, 1); // .. Clear
66 Error
67 }

To make the MotionParameter externally readable, the corresponding MOTIONCODE_PARAMETER must still be assigned
in the Get function.

Version 03-07-2024 Motioncode documentation Page 52 / 123


In the definition of the MotionParameter it was specified that it should be assigned to MOTIONCODE_PARAMETER_UI32_05 .
Since it is a storable parameter, an * operator must be used:

../src/MotionParameter.c motionCode_odGetParameter()

98 com_object_if_error_t motionCode_odGetParameter(void* const this,


com_object_if_variable_t* value)
99 {
100 com_object_if_error_t result = ERROR_NONE; // DO NOT
REMOVE - Initialization of motionCode_odGetParameter()
101
102 switch(PARAMETER)
{
103 /* uint32_t */
104 case MOTIONCODE_PARAMETER_UI32_01: // Assign
MOTIONCODE_PARAMETER_UI32_01 ..
105 value->ui32 = (motionParameter.myCommand); // .. to
106 motionParameter myCommand
break;
107 case MOTIONCODE_PARAMETER_UI32_02: // Assign
108 MOTIONCODE_PARAMETER_UI32_02 ..
value->ui32 = (motionParameter.myStatus); // .. to
109 motionParameter myStatus
110 break;
case MOTIONCODE_PARAMETER_UI32_03: // Assign
111 MOTIONCODE_PARAMETER_UI32_03 ..
112 value->ui32 = (motionParameter.debugProgramState); // .. to
motionParameter debugProgramState
113 break;
114 case MOTIONCODE_PARAMETER_UI32_04: // Assign
MOTIONCODE_PARAMETER_UI32_04 ..
115 value->ui32 = *(motionParameter.debounceTime); // .. to
116 storable motionParameter debounceTime
break;
117 case MOTIONCODE_PARAMETER_UI32_05: // Assign
118 MOTIONCODE_PARAMETER_UI32_05 ..
value->ui32 = *(motionParameter.nrOfRelPositionings); // .. to
119 storable motionParameter nrOfRelPositionings
break;

The main difference between storable and non storable motion parameters is that the storable ones are defined as
pointers. However, this alone is not enough to make it storable. It must still be assigned a fixed address.

In the function motionCode_init() fixed addresses are assigned in the EEPROM. A maximum of 128 motion
parameters can be stored. The memory function of the drive interface is used for this purpose. The value passed to the
memory function determines the position in the array in the EEPROM. The value passed must be between 0 and 127 and
may only be used once. The MotionParameter nrOfRelPositionings is linked to position 1 in the array as follows:

../src/MotionCode.c stateStartMoving()

198 void stateStartMoving(void)


{
199 motionParameter.debugProgramState = D_StateStartMoving; // Set
200 StateStartMoving for debugging
201 programSpecificFunctions_doRelPos(motionParameter.targetPosition,
202 motionParameter.targetVelocity); // Do relative positioning on 512 increments with 2000 rpm
203 motionParameter.myStatus = S_Moving; // Set
204 S_Moving
205 *motionParameter.nrOfRelPositionings
206 +=1; // Add 1 to nrOfRelPositionings
207 stateFunction = &stateNOP; // Do not
208 call this state again
}
209

However, counting up alone is not enough, it must also be stored. Since an EEPROM has only a finite number of storage
cycles, however, only every tenth time is to be stored. The storing itself is realized by the store function of the drive
interface. This function must still be passed which locations in the memory array (see motionCode_init() ) are to be
stored.

Version 03-07-2024 Motioncode documentation Page 53 / 123


Example

The digits 2, 5, 10 & 18 are to be stored in the memory array. This would be binary: 0100 000 0100 0010 0100
Thus the hexadecimal value 0x40424 would have to be passed to the store function: drive->storeExtended(0x00,
0x00, 0x00, 0x40424); In the case of the MotionParameter nrOfRelPositionings the value 0x2 must be passed to
the store function for location 1 in the array. So the store command looks like this: drive-> storeExtended(0x00,
0x00, 0x00, 0x2);

The finished stateStartMoving() including cycle counter and store the cycle counter then looks like this:

../src/MotionCode.c stateStartMoving()

198 void stateStartMoving(void)


{
199 motionParameter.debugProgramState = D_StateStartMoving; // Set
200 StateStartMoving for debugging
201 programSpecificFunctions_doRelPos(motionParameter.targetPosition,
202 motionParameter.targetVelocity); // Do relative positioning on 512 increments with 2000 rpm
203 motionParameter.myStatus = S_Moving; // Set
204 S_Moving
205 *motionParameter.nrOfRelPositionings
206 +=1; // Add 1 to nrOfRelPositionings
207 if((*motionParameter.nrOfRelPositionings % 10) == 0) // Every
208 10th time of increasing nrOfRelPositionings...
{
209 drive->storeExtended(0x00, 0x00, 0x00,
210 0x2); // .. store nrOfRelPositionings
}
211
212 stateFunction = &stateNOP; // Do not
call this state again
213 }
214

Now the MotionCode can be compiled again, loaded and tested with the DA5. For this, first the
MOTIONCODE_PARAMETER_UI32_04 is added to the parameter list:

Parametrization

Version 03-07-2024 Motioncode documentation Page 54 / 123


As an alternative to the parameter list, the oscilloscope function of the DA5 can also be used to record the parameter:

Oscilloscope Plot

At second 14,6 the electronics voltage was briefly switched off to check whether the saving worked. As can be seen,
the value falls back to the last stored value 10.

Version 03-07-2024 Motioncode documentation Page 55 / 123


Short examples of common functions

In this chapter numerous examples are listed where and how different tasks can be solved.

NodeID And Baud Rate Assignment (CANopen)

The NodeID and the baud rate may be set via the according motor objects.A change is only active when a CPU reset is
executed. For this either the logic voltage may be switched off and on from outside or a reset may be executed with the
motor object SYS_Command .

Communication Parameters

Service Parameters

Version 03-07-2024 Motioncode documentation Page 56 / 123


Currently, CANopen specific motor objects are not yet stored with parameter names. Instead index and subindex have to
be entered manually. An example object with the index 0x1234 and the subindex 0xAB would then correspond to the
value 0x1234AB. Writing the value 0 to this object would look like this:

Write value to Object

drive->writeUi32(0x1234AB, 0); // write value 0 on Index 0x1234 with Subindex 0xAB

A function which sets the NodeId and Baudrate could look like this:

fn_setNodeIdBaudrate()

Version 03-07-2024 Motioncode documentation Page 57 / 123


/*
*******************************************************************************
* Description:
* Example function. Set given NodeId and Baudrate and do CPU reset
*******************************************************************************
* Input values:
* int16_t NodeId --> desired NodeId
* int16_t Baudrate --> desired Baudrate
*******************************************************************************
*/
void fn_setNodeIdBaudrate(int16_t NodeId, int16_t Baudrate)
{
int16_t actualNodeId = 0;
drive->readI16(0x200002, &actualNodeId); // Read actual NodeId

int16_t actualBaudrate = 0;
drive->readI16(0x200003, &actualBaudrate); // Read actual Baudrate

if(actualNodeId != NodeId || actualBaudrate != Baudrate) // If NodeId or Baudrate has to


be changed ..
{
drive->writeUi32(0x200001, 0x6E657277); // .. activate writing
drive->writeI16 (0x200002, NodeId); // .. set NodeId
drive->writeI16 (0x200003, Baudrate); // .. set Baudrate

drive->writeUi32(0x242201, 0x20727374); // .. reset system


}
}

For changing the NodeId and baud rate the bootupRoutine() is useful:

../src/MotionCode.c bootupRoutine()

void bootupRoutine(void)
{
drive->restoreExtended(0xFFFFFFFFu, 0xFFFFFFFFu, 0xFFFFFFFFu, 0xFFFFFFFFu); // restore all
storable motion parameters
setNotStorableDefaultValues(); // Set default
values of not storable MotionParameter

fn_setNodeIdBaudrate(127,
4); // Set NodeId 127 and Baudrate 125kBaud/s

drive->writeUi8(DEVICE_Command, 1); // .. Clear Error


}

Danger

In the template the bootupRoutine() is executed directly after the MotionCode is uploaded. It can lead to error
messages during the upgrade, because the NodeId and baudrate could be changed before the upgrader is ready.
Therefore it is recommended not to realize the CPU reset in the software! Alternatively the call of the
bootupRoutine() can bedelayed.

PDO Mapping, Auto-Operational, Heartbeat In MotionCode (CANopen)

If one or more of the following points are to be initialized within the MotionCode:

PDO mapping
Auto-Operational
Heartbeat or Node-Guarding

It is recommended to store these parameters permanently. Only this way it is guaranteed that the firmware initializes a
correct CANopen communication directly at power-on.

Version 03-07-2024 Motioncode documentation Page 58 / 123


A function which activates and saves a PDO mapping and Auto-Operational would look like the following:

fn_setUpCanOpenPdoMappingAndAutoOp()

Version 03-07-2024 Motioncode documentation Page 59 / 123


/*
*******************************************************************************
* Description:
* Example function. Set up CANopen PDO-mapping and
* Auto-Operational and store it
*******************************************************************************
* Input values:
*******************************************************************************
*/
void fn_setUpCanOpenPdoMappingAndAutoOp(void)
{
/*-------------- First RX-PDO (Motor receiving) --------------*/
drive->writeUi32(0x140001u, 0xC0000000); // "CiA301_RPdo1CobId" --> Delete old CobId
drive->writeUi8(0x160000u, 0); // "CiA301_RPdo1MappingNumberOfObjects" -->
Delete old mapping
drive->writeUi32(0x160001u, 0x51020120); // "CiA301_RPdo1MappingObject1" --> MY_Command
// drive->writeUi32(0x160002u, 0x); // "CiA301_RPdo1MappingObject2" -->
// drive->writeUi32(0x160003u, 0x); // "CiA301_RPdo1MappingObject3" -->
// drive->writeUi32(0x160004u, 0x); // "CiA301_RPdo1MappingObject4" -->
drive->writeUi8(0x160000u, 1); // "CiA301_RPdo1MappingNumberOfObjects" --> 1
drive->writeUi8(0x140002u, 255); // "CiA301_RPdo1TransmissionType" --> 255
drive->writeUi32(0x140001u, 0x4000027F); // "CiA301_RPdo1CobId" --> Set new CobId 0x27F

/*------------- Second RX-PDO (Motor receiving) --------------*/


drive->writeUi32(0x140101u, 0xC0000000); // "CiA301_RPdo2CobId" --> Delete old CobId
drive->writeUi8(0x160100u, 0); // "CiA301_RPdo2MappingNumberOfObjects" -->
Delete old mapping
drive->writeUi32(0x160101u, 0x40000910); // "CiA301_RPdo2MappingObject1" -->
DEVICE_CommandSetErrorCode
// drive->writeUi32(0x160102u, 0x); // "CiA301_RPdo2MappingObject2" -->
// drive->writeUi32(0x160103u, 0x); // "CiA301_RPdo2MappingObject3" -->
// drive->writeUi32(0x160104u, 0x); // "CiA301_RPdo2MappingObject4" -->
drive->writeUi8(0x160100u, 1); // "CiA301_RPdo2MappingNumberOfObjects" --> 1
drive->writeUi8(0x140102u, 255); // "CiA301_RPdo2TransmissionType" --> 255
drive->writeUi32(0x140101u, 0x4000037F); // "CiA301_RPdo2CobId" --> Set new CobId 0x37F

/*------------ First TX-PDO (Motor transmitting) -------------*/


drive->writeUi32(0x180001u, 0x80000000); // "CiA301_TPdo1CobId" --> Delete old CobId
drive->writeUi8(0x1A0000u, 0); // "CiA301_TPdo1MappingNumberOfObjects" -->
Delete old mapping
drive->writeUi32(0x1A0001u, 0x51020220); // "CiA301_TPdo1MappingObject1" --> MY_Status
// drive->writeUi32(0x1A0002u, 0x); // "CiA301_TPdo1MappingObject2" -->
// drive->writeUi32(0x1A0003u, 0x); // "CiA301_TPdo1MappingObject3" -->
// drive->writeUi32(0x1A0004u, 0x); // "CiA301_TPdo1MappingObject4" -->
drive->writeUi8(0x1A0000u, 1); // "CiA301_TPdo1MappingNumberOfObjects" --> 1
drive->writeUi8(0x180002u, 255); // "CiA301_TPdo1TransmissionType" --> 255
drive->writeUi16(0x180003u,
200); // "CiA301_TPdo1InhibitTime" --> 20 ms (200 * 100 µs)
drive->writeUi32(0x180001u, 0x1FF); // "CiA301_TPdo1CobId" --> Set new CobId 0x1FF

/*------------ Second TX-PDO (Motor transmitting) ------------*/


drive->writeUi32(0x180101u, 0x80000000); // "CiA301_TPdo2CobId" --> Delete old CobId
drive->writeUi8(0x1A0100u, 0); // "CiA301_TPdo2MappingNumberOfObjects" -->
Delete old mapping
drive->writeUi32(0x1A0101u, 0x40020120); // "CiA301_TPdo2MappingObject1" -->
DEVICE_StatusRegister
// drive->writeUi32(0x1A0102u, 0x); // "CiA301_TPdo2MappingObject2" -->
// drive->writeUi32(0x1A0103u, 0x); // "CiA301_TPdo2MappingObject3" -->
// drive->writeUi32(0x1A0104u, 0x); // "CiA301_TPdo2MappingObject4" -->
drive->writeUi8(0x1A0100u, 1); // "CiA301_TPdo2MappingNumberOfObjects" --> 1
drive->writeUi8(0x180102u, 255); // "CiA301_TPdo2TransmissionType" --> 255
drive->writeUi16(0x180103u,
200); // "CiA301_TPdo2InhibitTime" --> 20 ms (200 * 100 µs)
drive->writeUi32(0x180101u, 0x2FF); // "CiA301_TPdo2CobId" --> Set new CobId 0x2FF

/*----------------- Enable Auto-Operational ------------------*/


drive->writeUi32(0x200001u, 0x6E657277); // "COM_ConfigWriteEnable" --> Enable writing
drive->writeUi16(0x200004u, 1); // "COM_ConfigAutoOperational" --> Enable AutoOp

/*-------------- Store communication parameters --------------*/


drive->writeUi32(0x101002u, 0x65766173); // "CiA301_SaveCommunicationParameters" --> save
drive->writeUi32(0x101005u, 0x65766173); //
"CiA301_SaveDunkermotorenCommunicationParameters" --> save
}

Version 03-07-2024 Motioncode documentation Page 60 / 123


A function which activates and saves Heartbeat would look like this:

fn_setUpCanOpenHeartbeat()

/*
*******************************************************************************
* Description:
* Example function. Set up CANopen Heartbeat and store it
*******************************************************************************
* Input values:
*******************************************************************************
*/
void fn_setUpCanOpenHeartbeat(void)
{
/*-------------- Set Heartbeat Motor is sending --------------*/
drive->writeUi16(0x101700u, 250); // "CiA301_ProducerHeartbeatTime" --> 250 ms

/*----------- Set Heartbeat(s) Motor is receiving ------------*/


drive->writeUi32(0x101601u, 0x0103E8); // "CiA301_ConsumerHeartbeatTime1" --> NodeId 1
with 1000 ms
// drive->writeUi32(0x101602u, 0x0203E8); // "CiA301_ConsumerHeartbeatTime2" --> NodeId 2
with 1000 ms
// drive->writeUi32(0x101603u, 0x0303E8); // "CiA301_ConsumerHeartbeatTime3" --> NodeId 3
with 1000 ms
// drive->writeUi32(0x101604u, 0x0403E8); // "CiA301_ConsumerHeartbeatTime4" --> NodeId 4
with 1000 ms

/*---------- Set behavior after Communication-Error ----------*/


drive->writeUi8(0x102901u, 1); // "CiA301_ErrorBehaviorCommunicationError"
// --> 0 = Change to NMT state Pre-operational
// --> 1 = No change of NMT state
// --> 2 = Change to NMT state Stopped

/*-------------- Store communication parameters --------------*/


drive->writeUi32(0x101002u, 0x65766173); // "CiA301_SaveCommunicationParameters" --> save
}

When saving motor objects it is recommended to do this only once: At the first execution of the MotionCode. The
NotificationType UPDATED_MOTION_CODE is suitable for this. However, the entire NotificationType must not last longer than
200 ms, otherwise a timeout occurs and the error message -6007 MC_CALLBACK_TIMEOUT is triggered.

To work around this timeout a global variable is allready created as a flag:

../src/MotionCode.c

/**---------------- Private variables & constants -----------------------------*/


static stateMachine stateFunction; // Generate
stateFunction from type stateMachine
static bool_t firstTimeExecuted = false; // Flag which is
true when the MotionCode is executed the first time

This is then set as true in the NotificationType UPDATED_MOTION_CODE :

../src/MotionCode.c motionCode_notification()

Version 03-07-2024 Motioncode documentation Page 61 / 123


/*
*******************************************************************************
* Description:
* This function is called by the system on certain notification types. The
* different notificationTypes are set by different events by the firmware.
* --> See MotionCode documentation for details.
* --> DO NOT REMOVE OR RENAME
*******************************************************************************
*/
void motionCode_notification (motion_code_notification_type_t notificationType)
{
switch(notificationType) // Determine
witch notoficationType is true
{
case UPDATED_MOTION_CODE: //
UPDATED_MOTION_CODE is called when the MotionCode is executed the first time
setStorableDefaultValues(); // .. set
default values of storable MotionParameters
drive->storeExtended(0xFFFFFFFFu, 0xFFFFFFFFu, 0xFFFFFFFFu, 0xFFFFFFFFu); // ..
store all storable MotionParameters
firstTimeExecuted = true; // .. set
firstTimeExecuted
break;
default:
break;
}
}

The functions that activate PDO mapping, Auto-Op and/or Hearbeat are then called if this flag is true:

../src/MotionCode.c motionCode_main()

Version 03-07-2024 Motioncode documentation Page 62 / 123


/**---------------- Public module function definitions ------------------------*/
/*
*******************************************************************************
* Description:
* This is the 'MotionCode main function' executed by the motor firmware.
* --> It defines the really running MotionCode
* --> DO NOT REMOVE OR RENAME
*******************************************************************************
*/
void motionCode_main(void* pd)
{
if(firstTimeExecuted == true) // If MotionCode
is executed the first time ..
{
fn_setUpCanOpenPdoMappingAndAutoOp(); // .. set up and
store POD-Mapping and Auto-Op
fn_setUpCanOpenHeartbeat(); // .. set up and
store Heartbeat

while(true) // .. do not
execute the MotionCode ..
{

motionCodeFunctionLib_checkMotionParameterStoreCmdExtended(motionParameter.motionParameterStoreCmd); // ..
just check motionParameterStoreCmd
}
}
else // Else (If
MotionCode is not executed the first time) ..
{

bootupRoutine(); // .. call bootup routine


stateFunction = &stateControl; // .. set
stateControl as first state

while(true) // .. while
MotionCode is running ..
{

motionCodeFunctionLib_checkMotionParameterStoreCmdExtended(motionParameter.motionParameterStoreCmd); // ..
check motionParameterStoreCmd
stateControl(); // .. .. call
state Control
stateFunction(); // .. .. call
state machine
}
}
}

Please save only once if possible!

Set MY_Command Via BUS Instead Of IO

The line that reads the digital inputs must be commented out or deleted:

../src/MotionCode.c stateControl()

void stateControl(void)
{
//motionParameter.myCommand = motionCodeFunctionLib_readDebouncedDigitalInputs(0xFF,
*motionParameter.debounceTime); // Read DigitalInputs into myCommand
static uint32_t oldMyCommand = C_Undefined; // Stored
internal variable to detect changes of myCommand

Version 03-07-2024 Motioncode documentation Page 63 / 123


Call Current State Only Once

Since the stateFunction() in motionCode_main() is called cyclically, the defined state is always called until the
stateFunction() is overwritten. If a state is to be called only once and then waited until MY_Command changes , the
stateNOP() is defined at the end as the next stateFunction:

set stateNop

stateFunction = &stateNOP; // Define stateNOP() as next state

Typical Step Chain For Movement

Often a new MY_Command not only calls one state, but triggers a whole step chain. The following typical step chain is
shown here as an example:

1. Start positioning with myCommand "C_StartMoving


2. As long as the motor is turning OUT1 blinks with 2Hz
3. As soon as target position is reached activate OUT1 permanently and wait 5 seconds
4. Deactivate power stage and OUT1

With MY_Command "C_StartMoving" the stateStartMoving() is called:

../src/MotionCode.c stateControl()

else if(motionParameter.myCommand != oldMyCommand) // If no error and


myCommand did change => define next state
{
oldMyCommand = motionParameter.myCommand; // .. Overwrite old
myCommand

switch(motionParameter.myCommand) // .. Define next


stateFunction depending on myCommand
{
case C_Stop: // .. If command ==
C_Stop ..
stateFunction = &stateStop; // .. .. go to
stateStop
break;
case C_StartMoving: // .. If command ==
C_StartMoving ..
stateFunction = &stateStartMoving; // .. .. go to
stateStartMoving
break;
default: // .. If command is
undefined ..
motionParameter.debugProgramState = D_StateUndefined; // .. .. set
StateUndefined for debugging
stateFunction = &stateControl; // .. .. do not
call any state
break;
}
}

In this stateStartMoving() the movement is started. In addition, the stateWaitForPosReached() is specified as the
next state:

../src/MotionCode.c stateStartMoving()

Version 03-07-2024 Motioncode documentation Page 64 / 123


/*
*******************************************************************************
* Description:
* This stateFunction is called if myCommand C_StartMoving is detected.
* --> It starts the motor.
*******************************************************************************
*/
void stateStartMoving(void)
{
motionParameter.debugProgramState = D_StateStartMoving; // Set
StateStartMoving for debugging

programSpecificFunctions_doRelPos(motionParameter.targetPosition,
motionParameter.targetVelocity);// Do relative positioning on TargetPosition with TargetVelocity

motionParameter.myStatus = S_Moving; // Set S_Moving

*motionParameter.nrOfRelPositionings += 1; // Add 1 to
NrOfRelPositionings
if((*motionParameter.nrOfRelPositionings % 10 )== 0) // If it is the
10th time of increasing NrOfRelPositionings
drive->store(0x2); // .. store
NrOfRelPositionings

stateFunction = &stateWaitForPosReached; // Next state =


stateWaitForPosReached()
}

As long as MY_Command does not change, stateControl() does not change the stateFunction to be executed. That means now the
stateWaitForPosReached() is called. In it the OUT1 is blinked with 2 Hz until the state STAT_Reached is true. Then the
stateWaitAfterPosReached() is specified as the next stateFunction:

../src/MotionCode.c stateWaitForPosReached()

void stateWaitForPosReached(void) // State-


Function: Executed after stateStartMoving()
{
motionParameter.debugProgramState = D_StateWaitForPosReached; // Set
StateWaitForPosReached for debugging

uint32_t actualStatusRegister = 0;
drive->readUi32(DEVICE_StatusRegister, &actualStatusRegister); // Read actual
value of DEVICE_StatusRegister

if((actualStatusRegister & STAT_Reached) == STAT_Reached) // If


TargetPosition reached ..
stateFunction = &stateWaitAfterPosReached; // .. next state
= stateWaitAfterPosReached()
else // As long as
TargetPosition is not reached ..
fn_flashOut1(2, 0); // .. flash OUT1
with 2 Hz
}

In this the OUT1 is activated. After 5 seconds waiting time the output stage and OUT1 are deactivated. Then this state
must no longer be called cyclically. This is achieved by specifying the stateNOP() as the next stateFunction:

../src/MotionCode.c stateWaitAfterPosReached()

Version 03-07-2024 Motioncode documentation Page 65 / 123


void stateWaitAfterPosReached(void) // State-
Function: Executed after stateWaitForPosReached()
{
motionParameter.debugProgramState = D_StateWaitAfterPosReached; // Set
StateWaitAfterPosReached for debugging

drive->writeUi8(DEVICE_IOdigitalOutputs, 2); // Enable OUT1

static uint32_t startTime = 0; // Static


variable to start timer
if(startTime == 0) // If state is
called first time ..
drive->readUi32(DEVICE_Timer, &startTime); // .. start timer

if(motionCodeFunctionLib_timerTrueAfterDelay(startTime, 5000000)) // If 5 seconds


are over ..
{
drive->writeUi8(DEVICE_EnablePowerStage, 0); // .. disable
power stage
drive->writeUi8(DEVICE_IOdigitalOutputs, 2); // .. disable
OUT1
startTime = 0; // .. reset
startTime for next time state is called
stateFunction =
&stateNOP; // .. do not call state again. Next state
= stateNOP()
}
}

Sleep Timer

Generally it is not recommended to write code which stops the complete program flow. During this time it is not possible
to react to error messages or command changes. If it must be done nevertheless, a hard delay can be realized as follows:

fn_delay()

/*
*******************************************************************************
* Description:
* Example function. Do nothing as long as timeDelay is over
*******************************************************************************
* Input values:
* uint32_t timeDelay --> Time for the delay in [µs]
*******************************************************************************
*/
void fn_delay(uint32_t timeDelay)
{
uint32_t startTime = 0;
drive->readUi32(DEVICE_Timer, & startTime); // read actual value
of DEVICE_Timer as startTime
while(!motionCodeFunctionLib_timerTrueAfterDelay(startTime, timeDelay)) // do nothing until
timeDelay is over
;
}

Generate Pulses At Digital Output Or Variable

If a single bit of a value has to be toggled with a fixed frequency, this can be realized using the predefined function
motionCodeFunctionLib_pulseTimer() . The following example shows how to make the digital output OUT1 flash while
the other digital outputs keep their state:

fn_flashOut1()

Version 03-07-2024 Motioncode documentation Page 66 / 123


/*
*******************************************************************************
* Description:
* Example function. Flash OUT1 with given Frequency [Hz]
*******************************************************************************
* Input values:
* uint32_t Frequency --> Frequency in [Hz]
* uint32_t startTime --> Value of DEVICE_Timer which is compared to [µs]
*******************************************************************************
*/
void fn_flashOut1(uint32_t Frequency, uint32_t startTime)
{
/*------------------ Calculate period time -------------------*/
uint32_t periodTime = 1000000 / Frequency; // periodTime = 1
second / Frequency [Hz]

/*----------- Define new value of digital outputs ------------*/


uint8_t actualDigitalOutputs = 0;
drive->readUi8(DEVICE_IOdigitalOutputs, & actualDigitalOutputs); // read actual value of
DEVICE_IOdigitalOutputs
uint8_t newDigitalOutputs = 0; // local variable to
calculate new value of digital Outputs

if(motionCodeFunctionLib_pulseTimer(startTime, periodTime))
newDigitalOutputs = actualDigitalOutputs | 2; // In the first half of
periodTime activate OUT1
else
newDigitalOutputs = actualDigitalOutputs & (uint8_t) ~2; // In the second half of
periodTime deactivate OUT1

/*------------- Set new value to digital outputs -------------*/


drive->writeUi8(DEVICE_IOdigitalOutputs, newDigitalOutputs);
}

Passing the startTime is only necessary if the first pulse must have the correct period. Otherwise a 0 can simply be passed.

Working With The Debug1-9 MotionParameters (Data Type Transformation)

If something does not work and you want to investigate what went wrong, you can use the predefined motion parameters
debug1-9. These all have the data type int32. To be able to write in the values of variables of other data types, a data type
transformation is needed. This works as follows:

Cast data type

int8_t int8_Variable = -8;


motionParameter.debug1 = (int32_t)(int8_Variable); // convert int8_t to int32_t

uint8_t uint8_Variable = 8;
motionParameter.debug2 = (int32_t)(uint8_Variable); // convert uint8_t to int32_t

int16_t int16_Variable = -16;


motionParameter.debug3 = (int32_t)(int16_Variable); // convert int16_t to int32_t

uint16_t uint16_Variable = 16;


motionParameter.debug4 = (int32_t)(uint16_Variable);// convert uint16_t to int32_t

uint32_t uint32_Variable = 32;


motionParameter.debug6 = (int32_t)(uint32_Variable);// convert uint32_t to int32_t

This data type conversion can also be used apart from the DEBUG1-9 MotionParameter. For this only the desired data type must be entered in the front
bracket!

Danger

If a value is converted into a smaller data type, information can be cut off/lost.

Version 03-07-2024 Motioncode documentation Page 67 / 123


If-else Branch Instead Of Switch-case In StateControl()

By default, a switch-case branch is used in the stateControl() to determine the next stateFunction based on myCommand:

However, it can also be useful to do this with an If-Else branch. For example, if a status must be queried in addition to
myCommand. The switch-case branch from the template can be replaced functionally as follows:

../src/MotionCode.c stateControl()

else if(motionParameter.myCommand != oldMyCommand) // If no error and


myCommand did change => define next state
{
oldMyCommand = motionParameter.myCommand; // .. Overwrite old
myCommand

switch(motionParameter.myCommand) // .. Define next


stateFunction depending on myCommand
{
case C_Stop: // .. If command ==
C_Stop ..
stateFunction = &stateStop; // .. .. go to
stateStop
break;
case C_StartMoving: // .. If command ==
C_StartMoving ..
stateFunction = &stateStartMoving; // .. .. go to
stateStartMoving
break;
default: // .. If command is
undefined ..
motionParameter.debugProgramState = D_StateUndefined; // .. .. set
StateUndefined for debugging
stateFunction = &stateControl; // .. .. do not
call any state
break;
}
}

../src/MotionCode.c stateControl()

else if(motionParameter.myCommand != oldMyCommand) // If no error and


myCommand did change => define next state
{
oldMyCommand = motionParameter.myCommand; // .. Overwrite old
myCommand

if(motionParameter.myCommand == C_Stop) // If command ==


C_Stop ..
{
stateFunction = &stateStop; // .. go to stateStop
}
else if(motionParameter.myCommand ==
C_StartMoving) // Else if command == C_StartMoving ..
{
stateFunction = &stateStartMoving; // .. go to
stateStartMoving
}
else // Else --> command
is undefined ..
{
motionParameter.debugProgramState = D_StateUndefined; // .. set
StateUndefined for debugging
tateFunction =
&stateControl; // .. do not call any state
}
}

Version 03-07-2024 Motioncode documentation Page 68 / 123


Create New Custom Header (.H And .C File)

It may be useful to move a part of the program into separate .c and .h files. For example, if two program sequences are to
run in parallel and a second stateMachine is built for this purpose.

The header file is placed in the "inc" folder:

New -> Header File

Create new header

The source file is placed in the "src" folder:

New -> Source File

Version 03-07-2024 Motioncode documentation Page 69 / 123


Create new source

Version 03-07-2024 Motioncode documentation Page 70 / 123


Then the .h file must be imported into MotionCode.c:

../src/MotionCode.c

/**---------------- Includes --------------------------------------------------*/


#include <stdint.h> // Include fixed
width integer types
#include <stdlib.h> // Include
general utilities
#include <stdbool.h> // Include
datatype bool
#include <MotionCode.h> // Include
MotionCode specific header
#include <MotionCodeNotificationType.h> // Include
MotionCode specific header
#include <MotionParameter.h> // Include
MotionCode specific header
#include <DriveLib.h> // Include
MotionCode specific header
#include <DriveLibIF.h> // Include
MotionCode specific header
#include <DriveParameters.h> // Include
MotionCode specific header
#include <MotionCodeFunctionLib.h> // Include
MotionCodeFunctionLib.h header
#include <ProgramSpecificFunctions.h> // Include
ProgramSpecificFunctions.h header
#include <MyOwnHeader.h> // Include
MyOwnHeader.h

Version 03-07-2024 Motioncode documentation Page 71 / 123


1.3.6 Debugging

Drive Assistant 5

Read And Write Motor Parameters

Using the Drive Assistant makes it possible to read and write motor parameters. To this open the parameterization and
add a parameter with the symbol:

The name of the desired parameter can now be entered in the parameter window. A list of all available parameters can be
found in the respective knowledge base.

Read And Write Motion Parameters

Motion parameters can be found under the following name: MOTIONCODE_PARAMETER_XX_X

Version 03-07-2024 Motioncode documentation Page 72 / 123


By pressing the read button, the current value of the parameter is read out once and can be seen in the "Actual Value"
column. A desired value can be entered in the "Desired Value" column and the value is written to the parameter by
pressing the write button. In the settings window, there are already ready-made settings for the most common functions.
The same applies to the motion parameter template in the MotionCode folder:

All further information on motion parameters is available in „8.3 Modul: MotionParameter.c“ auf Seite 65.

MotionCode Control

In the DA5 parameter list "Motion Code Config", important parameters that are used to operate the MotionCode are
available:

Version 03-07-2024 Motioncode documentation Page 73 / 123


In addition, the motion code status can be read out in the "Status Information" tab:

DEVICE_MotionCodeExecutionStatus

This parameter can be used to recall the current state of the MotionCode. If there is no MotionCode on the
motor, this is signaled with status bit 0.
DEVICE_MotionCodeEnable

This parameter can be used to activate or deactivate the MotionCode. By default this parameter is set to 1 =
MotionCode active.
DEVICE_MotionCodeCommand

This parameter can be used to delete the MotionCode. With the value: 0x4C4544 the MotionCode can be
definitely deleted. Thereafter, restoring is not possible.
DEVICE_MotionCodeDebugControl

This parameter enable or disable the MotionCode debugging. If a debug session was started from IDE it will be
enabled automatically and need to be cleared to switch to normal execution

Version 03-07-2024 Motioncode documentation Page 74 / 123


Debugging

The development environment also offers debugging. This allows the MotionCode to be stopped at any point and
parameters to be read out. However, the drive unit in the motor continues to run and the motor can continue to perform
all its basic functions.

Start Debug Session

Before the debug session could be started, the following steps must be completed:

1. the MotionCode need to be compiled (see Build Process).


2. the application must be transferred to the drive (see Programming the Hardware).
3. The drive must connected to the IDE (see Link to MotionCode IDE).

The debug session can now be started using the debug icon in the IDE. Eclipse will automatically change to the
Debug View. And halt at motionCode_main as entry point.

Info

with direct click on the debug icon the actual selcected Project will be taken for debugging. By click on the arrow
beside the debug icon the desired project can be selected.

Debug Window

The illustration shows Eclipse in the debug view. As in the C/C++ window, there are also different areas for different
functions.

exemplary view

Version 03-07-2024 Motioncode documentation Page 75 / 123


5

2
1

Text is not SVG - cannot display

1. Configuration
This window shows the respective debug program and its configuration.
2. Source Code
This window shows the current position in the source code. This allows you to see which steps are currently
being executed.
3. Console
The console in debug mode has the same functionality as in C/C++ mode.
4. Variables/Breakepoints
An overview of all currently set breakpoints is displayed here. Also all variables.
5. Assembler Debug
Eclipse offers the option of selecting Assembler Debugging in the toolbar. If this option is selected, the progress
or the current steps are displayed in this window.

Version 03-07-2024 Motioncode documentation Page 76 / 123


The diffrent windows can arranged simply via drag and drop. New windows can be added via Window -> Show View ->
Other... (1)

1.

Debug Process And Features

When starting a debug session, the running program is suspendet at the beginning of the main routine
motionCode_main . This is indicated by the grayed-out suspend button .

Version 03-07-2024 Motioncode documentation Page 77 / 123


Now it's possible to execute the program step by step and read out variables and their values at this time. The most
important functions are accessible directly from the menu bar (1) and are explained below.

1.

Breakpoints

A breakpoint also pauses the execution of the program at the location where the breakpoint is set whenever it is
hit.

Breakpoints can be set with a double-click on the marker bar next to the source code line. The line will be marked
with a blue circle now.

When the program is suspendet the blue arrow (1) (Instruction Pointer) shows where the program stands now and wich
line will be executed in the next step. Now we have the following options:

1.

Access Variables

During a debug session, you can display variable types, and change or disable variable values.

Version 03-07-2024 Motioncode documentation Page 78 / 123


The value of a Variable can read ou by hovering over the desired Variable. In the Variables window all accssessible
Variables from the actual function are shown to.

Mouse hoover Variables window

The value of a variable can also be changed. This is helpful to test how your program handles a particular value or
to influence the state machine.

Therefore, just click into the actual value of the variable, change it to the desired value, and confirm with the Enter
key.

Version 03-07-2024 Motioncode documentation Page 79 / 123


Tip

To monitor specific variables, the Expressions view can be used. Here, for example, the entire struct of
motionParameter is monitored. To add an expression, the name of the expression can be entered in the field
"Add new expression".

Step Into

Execute the current line, including any subroutines, and proceed to the next statement.

This means that if the Instruction Pointer stands on a function or similar it will "jump" directly into this function.

Info

it's not possible to jump into the internal functions like from motionCodeFunctionLib use Step Over instead or
if jumped in Step Return

Step Over

Execute the current line, following execution inside a routine.

This means that if the Instruction Pointer stands on a function it will execute the whole subroutine without "jump"
into this function.

Step Return

Continue execution to the end of the current routine, then follow execution to the routine's caller.

This causes the debugger to "jump out" of the respective function.

Resume

Resume execution of the currently suspended debug target.

Version 03-07-2024 Motioncode documentation Page 80 / 123


The debugger will stop at the next available break point.

Info

if no reacheable break poit is set the debugger could run into timeout and must be restarted!

Suspend

The debugging process is temporarily stopped and can then be resumed using the Resume button to continue
again.

Terminate

The entire debug process is canceled.

Remove all Terminated

Clears all terminated processes in Debug view.

Instruction Stepping Mode

Enable instruction stepping mode to examine a program as it steps into disassembled code.

Version 03-07-2024 Motioncode documentation Page 81 / 123


1.3.7 Software Documentation
This chapter contains detailed information about MotionCode.

Switch-on sequence

The following diagram shows the switch-on sequence:

Version 03-07-2024 Motioncode documentation Page 82 / 123


Firmware MotionCode

yes
MotionCode available?

no

motionCode_init()

Inizialise Communication

DO NOT SETUP OBJECTS...

yes
Has CRC of MotionCode...

no
motionCode_notification...

Executing tasks

yes
MotionCode available?

no

motionCode_main()...

Text is not SVG - cannot display

Module: MotionCode.c

System Function: MotionCode_notification

This function is called by the firmware as soon as a defined scenario occurs. In the function itself, a switch case branch
ensures what should happen in the case of which notification.

Version 03-07-2024 Motioncode documentation Page 83 / 123


The scenario "Update MotionCode" is true if the CRC of the MotionCode has changed. It is called before the actual
MotionCode (see Switch-on sequence). That means at the first start after the MotionCode has been uploaded, the
function is called and the notificationType = UPDATED_MOTION_CODE is passed as argument. The scenario "store motion
parameter" is planned as a further NotificationType. As long as this is not yet realized in the firmware, the ready-made
function motionCodeFunctionLib_checkMotionParameterStoreCmd() can be used (see MotionCodeFunctionLib.h).

The scenario "WatchdogTime Elapsed" comes true if the last setted timerLimit from watchdogTimerSet elapses. Whitin
this case Actions can be defined after a Watchdog timeout occures and the execution of MotionCode stops.
(see Function watchdogTimerSet).

Danger

It must be noted that the respective case may not last longer than 200ms. Otherwise the error message -6007
MC_CALLBACK_TIMEOUT is triggered.!

motionCode_notification

Declaration:

void motionCode_notification (motion_code_notification_type_t notificationType)

Arguments: Return values:

Argument Data type Description

notification Type Motion_code_notification_type_t Specifies the type of notification, currently only:


UPDATED_MOTION_CODE
WATCHDOG_TIME_ELAPSED

void

System Function: MotionCode_init

This function is called on system startup and before the motionCode_main function (see Switch-on sequence). It can be
used to create an initial state before executing the main program.

Info

Motor parameters must not be accessed in this function (see Switch-on sequence). This results in a serious error
(error code: -30000, fatal error).

motionCode_init

Declaration:

void motionCode_init(void);

Version 03-07-2024 Motioncode documentation Page 84 / 123


Arguments: Return values:

Argument Data type Description

void void -

void

System Function: MotionCode_main

This function is the main function of the MotionCode. Here the actually executed program is defined. By default the
program is executed in an endless loop. It is also possible to work without an endless loop, but then the
motionCode_main() function is only called again after the next CPU reset (switch logic voltage off and on). The function
is always called by the firmware when there is computing capacity left.

motionCode_main

Declaration:

void motionCode_main(void* pd);

Arguments: Return values:

Argument Data type Description

pd void* -

void

Module: MotionParameter.c

Motion parameters are variables that the user can define and use himself. These can be linked to motor parameters so
that they can be read and written externally (via CANopen, EC, PN).

The following functions are available:

Declare storable and non storable motion parameters


Define default values
Set and read values at runtime
Store parameters in EEPROM
Restore parameters from the EEPROM

The following parameters are available:

Version 03-07-2024 Motioncode documentation Page 85 / 123


dMove CO... dPro CO/EC/EI/PN...

Int32 50x Int32 50x


MOTIONCODE_PARAMETER_I32_01 (5101.01h) MOTIONCODE_PARAMETER_I32_01 (5101.01h)
(..) (..)
MOTIONCODE_PARAMETER_I32_50 (5101.32h) MOTIONCODE_PARAMETER_I32_50 (5101.32h)

UInt32 10x UInt32 50x


MOTIONCODE_PARAMETER_UI32_01 (5102.01h) MOTIONCODE_PARAMETER_UI32_01 (5102.01h)
(..) (..)
MOTIONCODE_PARAMETER_UI32_10 (5102.0Ah) MOTIONCODE_PARAMETER_UI32_50 (5102.32h)

Int16 10x Int16 50x


MOTIONCODE_PARAMETER_I16_01 (5103.01h) MOTIONCODE_PARAMETER_I16_01 (5103.01h)
(..) (..)
MOTIONCODE_PARAMETER_I16_10 (5103.0Ah) MOTIONCODE_PARAMETER_I16_50 (5103.32h)

UInt16 10x UInt16 50x


MOTIONCODE_PARAMETER_UI16_01 (5104.01h) MOTIONCODE_PARAMETER_UI16_01 (5104.01h)
(..) (..)
MOTIONCODE_PARAMETER_UI16_10 (5104.0Ah) MOTIONCODE_PARAMETER_UI16_50 (5104.32h)

Int8 10x Int8 50x


MOTIONCODE_PARAMETER_I8_01 (5105.01h) MOTIONCODE_PARAMETER_I8_01 (5105.01h)
(..) (..)
MOTIONCODE_PARAMETER_I8_10 (5105.0Ah) MOTIONCODE_PARAMETER_I8_50 (5105.32h)

UInt8 10x UInt8 50x


MOTIONCODE_PARAMETER_UI8_01 (5106.01h) MOTIONCODE_PARAMETER_UI8_01 (5106.01h)
(..) (..)
MOTIONCODE_PARAMETER_UI8_10 (5106.0Ah) MOTIONCODE_PARAMETER_UI8_50 (5106.32h)
Text is not SVG - cannot display

The CANopen address is always composed as follows -> The parameter name contains data type and number:
MOTIONCODE_PARAMETER_DD_NN

DD

DD determines the data type. This determines the index of the CANopen address:

I32 = 0x5101
UI32 = 0x5102
I16 = 0x5103
UI16 = 0x5104
I8 = 0x5105
UI8 = 0x5106

NN

Version 03-07-2024 Motioncode documentation Page 86 / 123


NN is a consecutive number from 01-50, which determines the subindex of the CANopen address:

01 = 0x01
05 = 0x05
10 = 0x0A
50 = 0x32

Module: MotionParameter.h

The motion parameters are declared in this module (see motion_parameter). In addition, the values of the motion
parameters myCommand, debugProgramState and myStatus are assigned to names so that the source code is easier to
read.

Enum: TagsForMyCommand

In this enum the values of the motion parameter myCommand are assigned to names. This makes the code more
readable. The C_Undefined must be assigned a value, which cannot occur. This is used in the template as initial value for
the variable oldMyCommand (see functionality-of-the-state-machine).

../inc/MotionParameter.h TagsForMyCommand

33 enum TagsForMyCommand
{
34 C_ClearError = 15, // Command
35 C_ClearError --> IN0=1 IN1=1 IN2=1 IN3=1 (IN4=0)
C_Stop = 0, // Command
36 C_Stop --> IN0=0 IN1=0 IN2=0 IN3=0 (IN4=0)
37 C_StartMoving = 1, // Command
C_StartMoving--> IN0=1 IN1=0 IN2=0 IN3=0 (IN4=0)
38 C_Undefined = 0xFF, //
39 Mandatory! Define value which cannot happen (for init of variable "oldMyCommand" in
stateControl)
};

Enum: TagsForDebugProgramState

In this enum the values of the MotionParameter debugProgramState are assigned to names. This makes the code more
readable. A value is assigned to each state of the stateMachine. This is done by taking the state name and changing the
first letter to a capital letter. In addition, a „D_“ is placed in front of it. The value can be chosen arbitrarily. The
MotionParameter ProgramState is used for debuggingto determine what state the MotionCode is currently in.

../inc/MotionParameter.h TagsForDebugProgramState

62 enum TagsForDebugProgramState
{
63 D_StateUndefined = 0,
64 D_StateError = 1,
D_StateNOP = 10,
65 D_StateStop = 20,
66 D_StateStartMoving = 30,
};
67
68
69

Version 03-07-2024 Motioncode documentation Page 87 / 123


Enum: TagsForMyStatus

In this enum the values of the motion parameter myStatus are assigned to names. This makes the code more readable.
The myStatus motion parameter should always represent the status that is passed on to the outside. If the status is
passed to the outside via digital outputs, this MotionParameter should always be set when a digital output is set.

../inc/MotionParameter.h TagsForMyStatus

47 enum TagsForMyStatus
{
48 S_Undefined = 0,
49 S_Error = 1,
S_ErrorCleared = 2,
50 S_Stopped = 10,
51 S_Moving = 20,
};
52
53
54

System Structure: Motion_parameter

Storable and non-storable motion parameters can be declared here. The structure can be changed and extended by the
programmer at will. Storable parameters are declared as pointers, non-storable parameters are declared as simple
variables. The reason is that 32 addresses are already declared for storable parameters in the "drive" interface (see Array
Memory). During initialization, this memory is then allocated to the pointers from the motion_parameter structure so that
easy access is possible via the structure elements.

motion_parameter

Declaration:

struct motion_parameter{}

Example:

The example shows the declaration of a storable ("vel01") and a non-storable ("state") motion parameter.

struct motion_parameter
{
/* storable motion parameter */
int32_t *vel01;
/* not storable motion parameter */
uint8_t state;
};

Module: MotionParameter.c

The default values of the MotionParameters are defined in this module. In addition, the MotionParameters are linked with
motor parameters to make them readable and writable from outside (via CANopen, EC, PN).

Function: SetNotStorableDefaultValues

This function sets the default values of the non-volatile motion parameters. The function is called every time MotionCode
is started during bootupRoutine() (see Template Overview and state machine).

setNotStorableDefaultValues

Version 03-07-2024 Motioncode documentation Page 88 / 123


Declaration:

void setNotStorableDefaultValues(void);

Arguments: Return values: Example:

Argument Data type Description

void void -

void

The example shows setting the default value for a motionParameter "motionParameter1" that cannot be stored to the
value 0.

void setNotStorableDefaultValues(void);
{
/* not storable motion parameter */
motionParameter.motionParameter1 = 0;
}

Function: SetStorableDefaultValues

In this function the default values of the storable motion parameters are defined. The function is called at the first start of
the MotionCode during the NotificationType UPDATED_MOTION_CODE (see motioncode_notification).

setStorableDefaultValues

Declaration:

void setStorableDefaultValues(void);

Arguments: Return values: Example:

Argument Data type Description

void void -

void

The example shows the setting of the default value for a storable motion parameter "motionParameter2" to the value 0.

void setStorableDefaultValues(void);
{
/* storable motion parameter */
*motionParameter.motionParameter2 = 0;
}

Version 03-07-2024 Motioncode documentation Page 89 / 123


Function: MotionCode_odGetParameter

With the function "motionCode_odGetParameter" a parameter can be made readable from outside. The desired
parameter is added to the switch-case structure as a new case, in which the value is assigned to the "value" function
parameter using the "call by reference" method.

motionCode_odGetParameter

Declaration:

extern com_object_if_error_t motionCode_odGetParameter(void* const this,


com_object_if_variable_t* value);

Arguments: Return values: Example:

Argument Data type Description

this void* const unused

value com_object_if_variable_t* Return value of the read access (call by reference)

com_object_if_error_t

The example shows a program section which makes the storable motion parameter "vel01" readable from outside via
parameter 5101.01h (Table: 1). Since a storable parameter is declared as a pointer, it must be dereferenced with the
dereferencing operator * when it is assigned. If the parameter is declared as a variable and cannot be stored, the *
operator cannot be used.

com_object_if_error_t motionCode_odGetParameter(void* const this, com_object_if_variable_t*


value)
{
com_object_if_error_t result = ERROR_NONE;
switch(PARAMETER)
{
case MOTIONCODE_PARAMETERI32_01:
value->i32 = *(motionParameter.vel01);
break;
default:
result = ERROR_OBJECT_NOT_EXIST;
break;
}
return result;
}

Function: MotionCode_odSetParameter

By means of the "motionCode_odSetParameter" function a parameter can be described from the outside. For this
purpose, the desired parameter is added to the switch-case structure as a new case, in which the value of the function
parameter "value" is then assigned to the parameter by the "call by value" method.

motionCode_odSetParameter

Declaration:

extern com_object_if_error_t motionCode_odSetParameter(void* const this,


com_object_if_variable_t value);

Version 03-07-2024 Motioncode documentation Page 90 / 123


Arguments: Return values: Example:

Argument Data type Description

this void* const unused

value com_object_if_variable_t* Transfer value of the write access

com_object_if_error_t

The example shows a program section which makes the storable motion parameter "vel01" writable from the outside
via parameter 5101.01h. Since a storable parameter is declared as a pointer, it must be dereferenced with the
dereferencing operator * when it is assigned. If it were a non-storable parameter declared as a variable, the * operator
would not be usable.

com_object_if_error_t motionCode_odSetParameter(void* const this, com_object_if_variable_t value)


{
com_object_if_error_t result = ERROR_NONE;
switch(PARAMETER)
{
case MOTIONCODE_PARAMETERI32_01:
*(motionParameter.vel01) = value.i32;
break;
default:
result = ERROR_OBJECT_NOT_EXIST;
break;
}
return result;
}

Module: ProgramSpecificFunctions.c & h

In this module own functions, variables, enums, etc. can be defined. By swapping out the clarity of MotionCode.c is
improved. We recommend a naming with "programSpecificFunctions" at the beginning:

Declaration:

uint8_t programSpecificFunctions_ExampleProgramSpecific(uint8_t input);

Arguments: Return values:

Argument Data type Description

input uint8 -

uint8

Dunker Interface: drive

With this interface it is possible to access the motor parameters via the MotionCode. The interface provides a read and
write function for parameters from the object dictionary and a save and restore function to store an array of motion
parameters in the EEPROM. Additionaly the WatchdogTimer can be set by this interface.

Version 03-07-2024 Motioncode documentation Page 91 / 123


Array: Memory

A connection to the memory can be established via the "memory” array, which contains 128 fields with 32 data bits each.
It represents the part of the EEPROM that is available for the MotionCode. The individual array elements can either be
assigned to directly storable motion parameters (see motion_parameter), or they can also be used freely.

Array definition:

drive_lib_if_memory_t** memory

Example data access:

drive->memory[0]->i32

Data types:

Designation Data type

f32 Float

i16 Int16

i32 Int32

i8 Int8

ui16 Uint16

ui32 Uint32

ui8 Uint8

Info

The number of array fields has been increased from 32 to 128 in MotionCodeLibrary version 0023.01.0!

Function: StoreExtended

With the function "storeExtended" fields from the array "memory" can be stored depending on a predefined mask.

storeExtended

Declaration:

bool_t (*storeExtended) (uint32_t mask3, uint32_t mask2,


uint32_t mask1, uint32_t mask0);

Danger

This command triggers a save in the EEPROM. The EEPROM has only a limited number of storage cycles. After
that, the EEPROM can be damaged!

Version 03-07-2024 Motioncode documentation Page 92 / 123


Arguments: Return values: Example Function call:

Argument Data type Description

mask3 Uint32 Mask for bitwise selection of memory fields 96 to 127

mask2 Uint32 Mask for bitwise selection of memory fields 64 to 95

mask1 Uint32 Mask for bitwise selection of memory fields 32 to 63

mask0 Uint32 Mask for bitwise selection of memory fields 0 to 31

Return value Data type Description

false BOOL ACTION NOT SUCCESSFUL

true BOOL ACTION SUCCESSFUL

all 128 fields are addressed:

drive->storeExtended(0xFFFFFFu, 0xFFFFFFu,
0xFFFFFFu, 0xFFFFFFu);

fields 0 to 15 are addressed:

drive->storeExtended(0x0u, 0x0u, 0x0u, 0xFFFFu);

Info

The number of array fields has been increased from 32 to 128 in MotionCodeLibrary version 0023.01.0!

Function: RestoreExtended

With the function "storeExtended" fields can be restored from the array "memory" depending on a predefined mask.

restoreExtended

Declaration:

bool_t (*restoreExtended) (uint32_t mask3, uint32_t mask2,


uint32_t mask1, uint32_t mask0);

Danger

A restore is not allowed directly after a store! A certain time must be waited in between. Otherwise this leads to a
simultaneous access to the memory of several functions!

Version 03-07-2024 Motioncode documentation Page 93 / 123


Arguments: Return values: Example Function call:

Argument Data type Description

mask3 Uint32 Mask for bitwise selection of memory fields 96 to 127

mask2 Uint32 Mask for bitwise selection of memory fields 64 to 95

mask1 Uint32 Mask for bitwise selection of memory fields 32 to 63

mask0 Uint32 Mask for bitwise selection of memory fields 0 to 31

Return value Data type Description

false BOOL ACTION NOT SUCCESSFUL

true BOOL ACTION SUCCESSFUL

all 128 fields are addressed:

drive->restoreExtended(0xFFFFFFu, 0xFFFFFFu,
0xFFFFFFu, 0xFFFFFFu);

fields 0 to 15 are addressed:

drive->restoreExtended(0x0u, 0x0u, 0x0u, 0xFFFFu);

Info

The number of array fields has been increased from 32 to 128 in MotionCodeLibrary version 0023.01.0!

Function: Write

The "write" function can be used to write onto a parameter from the object directory of the motor.

Declaration:

drive_lib_if_error_t (*writeUi8) (drive_parameters_t parameter, uint8_t srcValue);


drive_lib_if_error_t (*writeI8) (drive_parameters_t parameter, int8_t srcValue);
drive_lib_if_error_t (*writeUi16) (drive_parameters_t parameter, uint16_t srcValue);
drive_lib_if_error_t (*writeI16) (drive_parameters_t parameter, int16_t srcValue);
drive_lib_if_error_t (*writeUi32) (drive_parameters_t parameter, uint32_t srcValue);
drive_lib_if_error_t (*writeI32) (drive_parameters_t parameter, int32_t srcValue);
drive_lib_if_error_t (*writeUi64) (drive_parameters_t parameter, uint64_t srcValue);
drive_lib_if_error_t (*writeI64) (drive_parameters_t parameter, int64_t srcValue);
drive_lib_if_error_t (*writeFloat) (drive_parameters_t parameter, float_t srcValue);
drive_lib_if_error_t (*writeDouble) (drive_parameters_t parameter, double_t srcValue);
drive_lib_if_error_t (*writeString) (drive_parameters_t parameter, uint8_t* srcValue);

Version 03-07-2024 Motioncode documentation Page 94 / 123


Arguments: Return values: Example Function call:

Argument Data type Description

parameter drive_parameters_t Parameters from the object directory of the motor

srcValue Uint8 UInt64 The value to be described with which the parameter is described in the corresponding data
Int8 Int64 type
Uint16 Float
Uint32 String
Int32

Error code Value

DRIVE_NO_ERROR 0

DRIVE_VALUE_TOO_BIG 1

DRIVE_VALUE_TOO_SMALL 2

DRIVE_VALUE_NOT_SUPPORTED 3

DRIVE_NOT_ALLOWED_IN_ACTUAL_STATE 4

DRIVE_OUT_OF_RANGE 5

DRIVE_OBJECT_NOT_EXIST 6

DRIVE_GENERAL_ERROR 7

DRIVE_USER_CALLBACK_TIMEOUT 8

DRIVE_NO_READ_PERMISSION 9

DRIVE_NO_WRITE_PERMISSION 10

The example shows a description of the Dunker parameter 4000.01h - Device Command with the value 1
( CMD_ClearError ). The return value is transferred to the "Error” variable.

Error = drive->writeUi8(DEVICE_Command, 1u);

Function: Read

The "read" function can be used to read out a parameter from the object directory of the motor.

Declaration:

drive_lib_if_error_t (*readUi8) (drive_parameters_t parameter, uint8_t *destValue);


drive_lib_if_error_t (*readI8) (drive_parameters_t parameter, int8_t *destValue);
drive_lib_if_error_t (*readUi16) (drive_parameters_t parameter, uint16_t *destValue);
drive_lib_if_error_t (*readI16) (drive_parameters_t parameter, int16_t *destValue);
drive_lib_if_error_t (*readUi32) (drive_parameters_t parameter, uint32_t *destValue);
drive_lib_if_error_t (*readI32) (drive_parameters_t parameter, int32_t *destValue);
drive_lib_if_error_t (*readUi64) (drive_parameters_t parameter, uint64_t *destValue);
drive_lib_if_error_t (*readI64) (drive_parameters_t parameter, int64_t *destValue);
drive_lib_if_error_t (*readFloat) (drive_parameters_t parameter, float_t *destValue);
drive_lib_if_error_t (*readDouble) (drive_parameters_t parameter, double_t *destValue);
drive_lib_if_error_t (*readString) (drive_parameters_t parameter, uint8_t* destValue);

Version 03-07-2024 Motioncode documentation Page 95 / 123


Arguments: Return values: Example Function call:

Argument Data type Description

parameter drive_parameters_t Parameters from the object directory of the motor

destValue Uint8 UInt64 The current value of the parameter is written to "destValue" in the corresponding data type
Int8 Int64
Uint16 Float
Uint32 String
Int32

Error code Value

DRIVE_NO_ERROR 0

DRIVE_VALUE_TOO_BIG 1

DRIVE_VALUE_TOO_SMALL 2

DRIVE_VALUE_NOT_SUPPORTED 3

DRIVE_NOT_ALLOWED_IN_ACTUAL_STATE 4

DRIVE_OUT_OF_RANGE 5

DRIVE_OBJECT_NOT_EXIST 6

DRIVE_GENERAL_ERROR 7

DRIVE_USER_CALLBACK_TIMEOUT 8

DRIVE_NO_READ_PERMISSION 9

DRIVE_NO_WRITE_PERMISSION 10

The example shows a readout of the Dunker parameter 4002.01h - Status Register. The read value is written into the
"state” variable. The return value is transferred to the "Error” variable.

Error = drive->readUint8(DEVICE_StatusRegister, &state);

To be able to read or write motion parameters from outside (for example: PLC), the respective parameters must be entered in the "get" and "set"
methods provided for this purpose.

Function: WatchdogTimerSet

The "watchdogTimerSet" function can be used to monitor the timely execution of the program by a watchdog timer. The
WatchdogTimer is activated with timerLimit > 0. If the Timer elapses the notificationType WATCHDOG_TIME_ELAPSED will be
raised. Afterwards the execution of the MotionCode stops and the execution state of the MotionCode will persists in Error
until rebooting the Application. With the Parameter DEVICE_MotionCodeWatchdogErrorEnable = 1 (default) additionally
the error code MA_MAIN_TIMEOUT (-6008) could be raised which is readable over Parameter DEVICE_ErrorCode .

Declaration:

uint32_t (*watchdogTimerSet) (uint32_t timerLimit);

Version 03-07-2024 Motioncode documentation Page 96 / 123


Arguments: Return values: Example Function call:

Argument Data type Description

timerLimit uint32_t Time in μs until WatchdogTimer elapses

Data type Description

uint32_t Elapsed time since last WatchdogTimer reset in μs

The example shows a reset of the WatchdogTimer for another 2 milliseconds:

drive->watchdogTimerSet(2000);

This example shows how the WatchdogTimer is set to zero to disable it:

drive->watchdogTimerSet(0);

Info

Minimum required MotionCode Library Version 0002D.00.0

Module: MotionCodeFunctionLib.h

Here predefined functions are provided which are frequently used. In addition, the individual bits of the
DEVICE_StatusRegister are assigned to names to make the program more readable. The module is already integrated
and the functions can be used immediately.

Enum: MotionCodeFunctionLib_tags_for_DEVICE_StatusRegister

In this enum all bits of the motor parameter DEVICE_StatusRegister are defined with names, so that the program
becomes better readable.

Function: MotionCodeFunctionLib_readDebouncedDigitalInputs

This function returns the debounced value of the digital inputs. The function must be called cyclically for this purpose.

motionCodeFunctionLib_readDebouncedDigitalInputs

Declaration:

uint8_t motionCodeFunctionLib_readDebouncedDigitalInputs(uint8_t digitalInputMask, uint32_t


debounceTime);

Version 03-07-2024 Motioncode documentation Page 97 / 123


Arguments: Return values: Example:

Argument Data type Description

digitalInputMask Uint8_t Masks the relevant inputs

debounceTime Uint32_t Debounce time [ms]

Return value Data type Description

digitalInputsLastValidValue uint8_t debounced & masked digital inputs

In the template this function is already used to read the digital inputs into the MotionParameter myCommand in
stateControl() :

motionParameter.myCommand = motionCodeFunctionLib_readDebouncedDigitalInputs(0xFF,
*motionParameter.debounceTime);

The debounce time is defined by the motion parameter debounceTime [ms] predefined in the template.

Danger

The function should always be called with the same digitalInputMask! Otherwise debouncing will always restart and
it will not work anymore!

Function: MotionCodeFunctionLib_timerTrueAfterDelay

This function returns the value "true" if a given time difference "timeDelay" has expired since the given timestamp
"startTime". If the time has not yet elapsed, the value "false" is returned. The motor parameter DEVICE_Timer is used for
this. This counts up in μs steps and overflows after one hour at the value 3'600'000'000. The function
motionCodeFunctionLib_timerTrueAfterDelay() intercepts an overflow. Thus delays up to 30 minutes (1'800'000'000 μs)
can be determined.

motionCodeFunctionLib_timerTrueAfterDelay

Declaration:

bool motionCodeFunctionLib_timerTrueAfterDelay(uint32_t startTime, uint32_t timeDelay);

Version 03-07-2024 Motioncode documentation Page 98 / 123


Arguments: Return values: Example

Argument Data type Description

startTime Uint32_t Value of the DEVICE_Timer motor parameter at timerstart [μs]

timeDelay Uint32_t Time difference after which the value "true" is returned [μs]

Return value Data type Description

false BOOL timeDelay not elapsed

true BOOL timeDelay elapsed

a State that enables out1 for 5 seconds

// State-Function: Enable OUT1 for 5 seconds, then disable it


// Call this state cyclic!!!
void stateEnableOut1For5Seconds(void)
{
motionParameter.debugProgramState = D_StateEnableOut1For5Seconds; // Set
StateWaitAfterPosReached for debugging

drive->writeUi8(DEVICE_IOdigitalOutputs, 2); // Enable OUT1

static uint32_t startTime = 0; // Static


variable to start timer

if(startTime ==
0) // If state is called
first time ..
drive->readUi32(DEVICE_Timer, &startTime); // .. start timer

if(motionCodeFunctionLib_timerTrueAfterDelay(startTime, 5000000)) // If 5 seconds (5’000’000


μs) are over ..
{
drive->writeUi8(DEVICE_IOdigitalOutputs, 2); // .. disable
OUT1

startTime =
0; // .. reset startTime
for next time state is called

stateFunction = &stateNOP; // .. do
not call state again. Next state = stateNOP()

}
}

Danger

If this function is used, the motor parameter DEVICE_Timer must not be overwritten! The function should be called
cyclically.

Function: MotionCodeFunctionLib_pulseTimer

This function returns alternately the value "true" and "false". The period duration "periodTime" returns the time difference
between two edges from "true" to "false". In the first half of the period duration the value "true" is returned. In the second
half of the period duration the value "false" is returned. So that already the first period duration has the correct length, the
timestamp "startTime" must be specified at the beginning. If it does not matter whether the first period duration is shorter,
this value must not be transferred correctly, then a 0 can also be transferred. In this case the motor parameter
DEVICE_Timer is used. This counts up in μs steps and overflows after one hour at the value 3'600'000'000. The function
motionCodeFunctionLib_pulseTimer( ) intercepts an overflow. Thus period durations up to 30 minutes
(1'800'000'000 μs) can be achieved.

motionCodeFunctionLib_pulseTimer

Version 03-07-2024 Motioncode documentation Page 99 / 123


Declaration:

bool motionCodeFunctionLib_pulseTimer(uint32_t startTime, uint32_t periodTime);

Arguments: Return values: Example

Argument Data type Description

startTime Uint32_t Value of the motor parameter DEVICE_Timer at the start of the timer. If the first period duration may
also be shorter,the value 0 can also be transferred [μs]

periodTime Uint32_t Period duration in the first half of which the value "true" is returned and in the second half "false" [μs]

Return value Data type Description

true BOOL first half period

false BOOL second half period

See -> Generate pulses at digital output or variable

Danger

If this function is used, the motor parameter DEVICE_Timer must not be overwritten! The function must be called
cyclically.

Function: MotionCodeFunctionLib_checkMotionParameterStoreCmdExtended

This function checks whether a positive edge from 0 to 1 has occurred at the passed MotionParameter
motionParameterStoreCmd ( MOTIONCODE_PARAMETER_I32_50 - 5101.32h). If yes, it stores the current values of all

Version 03-07-2024 Motioncode documentation Page 100 / 123


storable MotionParameters into the EEPROM. In order for the saving to work using MotionParameter
motionParameterStoreCmd, the function must be called cyclically! In the template the function is already called cyclically:

../src/MotionCode.c motionCode_main

196 void motionCode_main(void* pd)


{
197 if(firstTimeExecuted == true) // If
198 MotionCode is executed the first time ..
{
199 while(true) // .. do
200 not execute the MotionCode ..
{
201
202 motionCodeFunctionLib_checkMotionParameterStoreCmdExtended(motionParameter.motionParameterStoreCmd);
just check motionParameterStoreCmd
203 }
204 }
205 else // Else (If
206 MotionCode is not executed the first time) ..
{
207 bootupRoutine(); // .. call
208 bootup routine
stateFunction = &stateControl; // .. set
209 stateControl as first state
210
211 while(true) // .. while
212 MotionCode is running ..
{
213
214 motionCodeFunctionLib_checkMotionParameterStoreCmdExtended(motionParameter.motionParameterStoreCmd);
check motionParameterStoreCmd
215 stateControl(); // .. ..
216 call state Control
stateFunction(); // .. ..
217 call state machine
}
}
}

If defined storable MotionParameters are to be included in a parameter set, this storage command must also be included
in the parameter set. In future, this function is to be replaced by a NotificationType (see motionCode_notification).

motionCodeFunctionLib_checkMotionParameterStoreCmdExtended

Declaration:

void motionCodeFunctionLib_checkMotionParameterStoreCmdExtended(int32_t actStoreCmd);

Arguments: Return values:

Argument Data type Description

actStoreCmd Int32_t A positive edge from 0 to 1 triggers a save command for all storable motion parameters

void

Info

The number of array fields has been increased from 32 to 128 in MotionCodeLibrary version 0023.01.0! At the same
time the function motionCodeFunctionLib_checkMotionParameterStoreCmdExtended has replaced the former
function motionCodeFunctionLib_checkMotionParameterStoreCmd !

Version 03-07-2024 Motioncode documentation Page 101 / 123


Memory capacity

The memory is divided into ROM and RAM. The motion code and the read-only data are stored in ROM. The read-write
data (local and global variables, as well as motion parameters) are stored in the RAM. The following table shows how
much ROM and RAM is available for the motion code in the different electronics variants:

Variant ROM (code and read only data) RAM (Read Write Data)

dMove CO 65536 Bytes 4096 Bytes

dPro CO/EC/PN/IE 131072 Bytes 8192 Bytes

The values apply regardless of the motor/controller (BGE5510, BG66, BG75, BG95, ...).

ROM (Code And Read Only Data)

The ROM stores the compiled MotionCode and read-only data. Read-only data means for example the initial value of a
variable:

uint32_t myVariable = 0x1234;

In this example the variable myVariable occupies 4 bytes in RAM and the initial value 0x1234 occupies another 4 bytes in ROM. During compilation it is
checked if the MotionCode fits into the ROM. If not, an error message is output. As the MotionCode is compiled, it is not possible to predict the
maximum number of lines of code that can be programmed until the ROM is full. However, to get a feeling, the following table shows the ROM
requirement of already written MotionCodes:

MotionCode dMove (max. dPro (max.


65536 Bytes) 131072 Bytes)

Template with 184 program lines occupies 13176 bytes 20 % 10 %

MotionCode with 1161 program lines occupies 19256 bytes 30 % 15 %

Largest MotionCode written so far with 2263 program lines occupies 47900 bytes 73 % 37 %
(Comparable MPU had needed 100% MPU memory at that time)

Test program with 10000 lines occupies 91520 bytes 140 % 70 %

RAM (Read-Write-Data)

The read-write data is stored in RAM. These are the motion parameters, local and global variables. Functions used from
libraries can also contain variables and fill the RAM additionally. In addition, when variables are passed to functions, local
variables are also created. If too many global variables are declared, this leads to a linker error during compilation.
However, it is not checked whether in addition to the global variables also the local variables fit into the RAM. This must
be ensured by the user.

dMove (max. 4096 Bytes) dPro (max. 8192 Bytes)

Template occupies 3200 bytes 78,13 % 39,06 %

All 100 MotionParameters together occupy 300 bytes 7,32 % 3,66 %

Usable RAM for variables when all motion parameters are defined 652 Byte (163 32bit variables) 4748 Byte (1187 32bit variables)

Determine Memory Consumption Of The MotionCode

After the build process, a *.map file (map file) can be found in the output folder. It lists the memory consumption for
different segments in hexadecimal format. The first line of each segment indicates its total consumption. The map file is
named like the project:

Version 03-07-2024 Motioncode documentation Page 102 / 123


Three values must now be determined in this map file:

Version 03-07-2024 Motioncode documentation Page 103 / 123


dMove CO dPro CO

The .text segment contains code and read only data, which are placed in the ROM.

1148 .text 0x08010030 0x33b4


0x08010030 __text_start__ = .
1149 *(.isr_vector)
1150 *(.text*)
1151

The segment .data contains all initialized global variables, which are placed in RAM.

1633 .data 0x2000f000 0x1ac load address 0x080133e4


0x2000f000 __data_start__ = .
1634 *(vtable)
1635 *(.data*)
1636

The segment .bss contains all uninitialized or zero-initialized global variables which are placed in RAM.

1948 .bss 0x2000f1b0 0xd10 load address 0x08013598


0x2000f1b0 . = ALIGN (0x4)
1949 0x2000f1b0 __bss_start__ = .
1950 *(.bss)
*(.bss*)
1951
1952

Thus the template (V 2.03) occupies 13236 bytes in ROM and 3772 bytes in RAM (428 + 3344).

The .text segment contains code and read only data, which are placed in the ROM.

348 .text 0x08020030 0x51e8


0x08020030 __text_start__ = .
349 *(.isr_vector)
350 *(.text*)
351

The segment .data contains all initialized global variables, which are placed in RAM.

1233 .data 0x2000e000 0x4cc load address 0x08025218


0x2000e000 __data_start__ = .
1234 *(vtable)
1235 *(.data*)
1236

The segment .bss contains all uninitialized or zero-initialized global variables which are placed in RAM.

2148 .bss 0x2000e4d0 0xd10 load address 0x080256e8


0x2000e4d0 . = ALIGN (0x4)
2149 0x2000e4d0 __bss_start__ = .
2150 *(.bss)
*(.bss*)
2151
2152

Thus the template (V 2.03) occupies 20968 bytes in ROM and 4572 bytes in RAM (1228 + 3344).

Version 03-07-2024 Motioncode documentation Page 104 / 123


Error Description

Details of all error messages can be found in the KnowledgeBase:

Version 03-07-2024 Motioncode documentation Page 105 / 123


Error code Description

-114 The MotionCode is not compatible with the motor firmware. For example, if a dMoveCO MotionCode is to be played on a dPro
-110 motor.

-6000 An attempt is made to read a motion parameter although no motion code is active in the motor. Often there is another error
behind it and this must first be acknowledged to see the cause

-6001 An undefined error occured in the MotionCode.

-6002 The downloaded MotionCode has wrong CRCs.

-6003 The communication interface (CANopen, Profinet, ...) of the MotionCode is incompatible with the firmare.

-6004 The MotionCode has a newer MotionCodeLibrary version than the motor firmware provides. (see Project Properties).

-6005 The entry address of the MotionCode was not found by the firmware during startup.

-6006 The upgrade notification failed. Possible reasons are a missing notification function of the MotionCode or a memory error.

-6007 The consumed time when reading/writing a motion parameter is too high. A possible reason is an endless loop inside the
MotionCode.

-6008 The MotionCode watchdog time has elapsed. See DEVICE_MotionCodeWatchdogErrorEnable

-6010 A read or write function of the drive interface was called with a NULL pointer as argument.

-6011 The MotionCode tried to access protected memory regions.


- The number of storable motion parameters in the motionParameter.h structure must match the number of parameter entries in
the motionCode_init function.
- "stateFunction" points to "void" or was not assigned.

-6012 The MotionCode contains a illegal division with zero.

General errors

It must be ensured that no MotionConfig or other parameters are stored on the motor, as otherwise an unintentional behavior may occur. It is best to
execute a Restore to Default command before installing the MotionCode.

If digital inputs are detected incorrectly, this could be due to a mechanical bounce of the switch/button. A debounce function can help (see
readDebouncedDigitalInputs).

To enable changes to project properties to be adopted, the project must be rebuilt

Version 03-07-2024 Motioncode documentation Page 106 / 123


For other errors/problems, it is also worth taking a look at the "FAQ". This covers various minor problems and how to
solve them.

Version 03-07-2024 Motioncode documentation Page 107 / 123


1.4 Release Notes

1.4.1 Version
This document was created on the basis of the following versions:

Module Version

MotionCode IDE 4.0.0

MotionCode Template 2.5.0

MotionCode Library Version 0002D.00.0

MotionCode Function Library 0002.00.0

Drive Assistant 5 18.1.0

Version 03-07-2024 Motioncode documentation Page 108 / 123


1.5 FAQ

1.5.1 Upgrade older MC-Projects

IDE 2.X.X to IDE 3.0.0 or newer

In the MotionCode IDE 3.0.0 a newer version of the GNU compiler is used as before. This leads to the following errors:

To make the old project compatible the existing variable MotionParameter must be declared as extern in
MotionParameter.h:

Additionally, the variable must be defined in MotionParameter.c:

Version 03-07-2024 Motioncode documentation Page 109 / 123


IDE 2.0.1 to IDE 2.0.3 or newer

If an older project is included into a newer MotionCode IDE version the following includes do not work:

The following include path must be added to the project properties:

Include path:

"${eclipse_home}/dunkermotoren/MotionCodeLibrary/${MOTIONCODE_LIBRARY_VERSION}/inc"

Include MotionCodeFunctionLib.h into existing projects from older IDE versions

Create the Build Variable MOTIONCODE_FUNCTIONLIBRARY_VERSION in the project properties:

Version 03-07-2024 Motioncode documentation Page 110 / 123


Add the include Path in the project properties:

Include path:

Version 03-07-2024 Motioncode documentation Page 111 / 123


"${eclipse_home}/dunkermotoren/MotionCodeLibrary/MotionCodeFuntionLibrary/$
{MOTIONCODE_FUNCTIONLIBRARY_VERSION}/inc"

Add Library and Library Path in the project properties:

Librarie:

MotionCodeFunctionLib

Include path:

"${eclipse_home}/dunkermotoren/MotionCodeLibrary/MotionCodeFunctionLibrary/$
{MOTIONCODE_FUNCTIONLIBRARY_VERSION}"

1.5.2 MotionParameters cannot be stored


MotionCodeFunctionLib Version 1.0.0 (fixed since version 2.0.0)

In MotionCodeFunctionLib.h version 0001.00.0 was a small bug: The function


motionCodeFunctionLib_checkMotionParameterStoreCmd(void) sometimes did not work.

This is fixed in version 0002.00.0. Change the used version in the build variables:

Version 03-07-2024 Motioncode documentation Page 112 / 123


Add the given value in MotionCode_main() to motionParameter.motionParameterStoreCmd:

1.5.3 Some storable MotionParameters cannot be stored


Since MOTIONCODE_LIBRARY_VERSION 00023.00.0 the number of storable MotionParameters is increased from 32 to 128.

Therefor two new functions were introduced:

drive->restoreExtended(uint32_t mask3,uint32_t mask2, uint32_t mask1, uint32_t mask0);


drive->storeExtended(uint32_t mask3,uint32_t mask2, uint32_t mask1, uint32_t mask0);

Version 03-07-2024 Motioncode documentation Page 113 / 123


The older once are still available for backward compatibility:

drive->restore(uint32_t mask);
drive->store(uint32_t mask);

If you assign EEPROM array fields 32-127 in motionCode_init() the new commands must be used to store restore:

Additional in MOTIONCODE_FUNCTIONLIBRARY_VERSION 0002.00.0 the following function is new introduced:

motionCodeFunctionLib_checkMotionParameterStoreCmdExtended(int32_t actStoreCmd);

Change in the build variables to this version (or newer) and use the new function in MotionCode_main() :

Version 03-07-2024 Motioncode documentation Page 114 / 123


1.5.4 Error Messages:

Error Program "make" not found in PATH

Eclipse has a known bug, that path configurations sometimes get deleted while closing the IDE. The result is the error
Program "make" not found in PATH while compiling. To restore the path configuration go to settings:

Version 03-07-2024 Motioncode documentation Page 115 / 123


Then into MCU and set the paths there:

Here the paths for copy paste:

Include paths:

Version 03-07-2024 Motioncode documentation Page 116 / 123


${eclipse_home}\toolchains\gcc-arm-none-eabi-10.3-2021.10\bin
${eclipse_home}\toolchains\xpack-windows-build-tools-4.2.1-2\bin

Error "undefined reference to motionCodeFunctionLib_checkMotionParameterStoreCmdExtended"

(fixed since 3.2.0)

If you get the following error:

You can fix it by deleting the file libMotionCodeFunctionLib.a out of the following subfolders in your MotionCode-IDE
installation path: - (…)\eclipse\dunkermotoren\MotionCodeLibrary\00023.00.0\dMoveCO - (…)
\eclipse\dunkermotoren\MotionCodeLibrary\00023.00.0\dProCO - (…)
\eclipse\dunkermotoren\MotionCodeLibrary\00023.00.0\dProEC - (…)
\eclipse\dunkermotoren\MotionCodeLibrary\00023.00.0\dProEI - (…)
\eclipse\dunkermotoren\MotionCodeLibrary\00023.00.0\dProPN

Also the file MotionCodeFunctionLib.h out of the following path should be deleted: - (…)
\eclipse\dunkermotoren\MotionCodeLibrary\00023.00.0\inc

Version 03-07-2024 Motioncode documentation Page 117 / 123


Error “xx kann syntaktisch (..) nicht verarbeitet werden”

Error message in Console:

The MOTIONCODE_VARIANT_NAME in not valid


There is no space allowed:

Avoid space in the string ->

Error “undefined reference to” function from imported header

This is a general c-problem.

To solve it an option of the indexer must be changed: For example we included the math.h header and wanted to use the
log() function:

Version 03-07-2024 Motioncode documentation Page 118 / 123


To solve it go into the properties of the project:

Then go to C/C++ Build-> Settings-> Cross ARM GNU C Linker-> Libraries and add into the Libraries a “m” (you must do
this for dMoveCO, dProCO, dProEC and dProPN separately!):

Version 03-07-2024 Motioncode documentation Page 119 / 123


Error “Build Project has encountered a problem”

If the following error occurs:

Version 03-07-2024 Motioncode documentation Page 120 / 123


It can be easily solved: - Change the Build Variables to “all configurations” and change the values here.

Otherwise there can be some problems in the background while the build process.

Version 03-07-2024 Motioncode documentation Page 121 / 123


1.5.5 Creating new project – Many errors in the template
If many lines are marked with errors the linker must reload. Therefor change the used Indexer ones (and maybe set it
back):

1.5.6 Parameter MOTOR_MaxCurrent cannot be resolved


The parameter is missing in the Parameter-List. Following Code must be used instead:

drive->writeUi32(0x490108, 14400);

1.5.7 Storing CAN-Communication Parameters while NotificationType UPDATED_MOTION_CODE


does not work
In the actual version it is not possible to store the communication parameters (example PDO mapping) while the
notification type UPDATED_MOTION_CODE. It causes the error -6007 MC_CALLBACK_TIMEOUT . The timeout is generated
when the NotificationType takes longer then 200 ms. Because storing CAN communication parameters takes more then
125ms it is not possible to store them here.

Avoid storing motor parameters out of the MotionCode!


Try to use the parameter set Init.xml instead and let the Upgrader store the parameters.
If it cannot be avoided to store out of the MC use the firstTimeExectuted flag and store in the
motionCode_main() function!

Version 03-07-2024 Motioncode documentation Page 122 / 123


Dunkermotoren GmbH | Allmendstraße 11 | D-79848 Bonndorf/Schwarzwald
Phone +49 (0) 7703 930-0 | Fax +49 (0) 7703 930-210/212 | info.dunkermotoren@ametek.com

You might also like