01 Manual MotionCode 240703
01 Manual MotionCode 240703
Table of contents
1. MotionCode 3
1.1 Overview 3
1.2 Set Up 4
1.3 Usage 6
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.
1.2.1 Requirements
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
Download
Hint
If the ZIP file can't be unpacked, the contents must be allowed via "Right click » Properties » General » Security".
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
Download
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.
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
1 5 4
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.
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).
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.
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
Export Settings
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
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.
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
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
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.
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.
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.
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).
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).
Note
Upgrader.exe
The appropriate upgrader for the selected build configuration (e.g. dMoveCO or dProPN) is automatically created in the
"MCPUpgrader" subfolder.
DriveAssistant 5
It's also possible to use the upgragder Functionality from the IDE
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.
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.
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.
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.
Select Port
Select Port
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
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".
By running Upgrader.exe the following interface opens and the upgrade can be started:
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.
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.
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:
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
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
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!
Object Description
MotionCode.c
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.
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
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.
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:
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:
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:
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:
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.
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.
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
../inc/MotionCode.c stateStop()
With digital input IN1 equal to one, the command C_StartMoving is executed and the stateStartMoving() is called:
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
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()
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:
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
../src/MotionCode.c stateStop()
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
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
../src/MotionCode.c stateWaitForStop()
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()
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()
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:
../src/MotionCode.c stateWaitForStop()
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()
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.
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.
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
../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
../src/MotionParameter.c motionCode_odGetParameter()
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()
../src/MotionCode.c stateStartMoving()
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.
1.
By clicking on the new parameters can be added. Either the complete parameter name or only a part can be
entered:
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
../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!!
../src/MotionCode.c motionCode_notification()
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.
../src/MotionParameter.c motionCode_odGetParameter()
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()
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.
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()
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
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.
In this chapter numerous examples are listed where and how different tasks can be solved.
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
A function which sets the NodeId and Baudrate could look like this:
fn_setNodeIdBaudrate()
int16_t actualBaudrate = 0;
drive->readI16(0x200003, &actualBaudrate); // Read actual Baudrate
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
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.
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.
fn_setUpCanOpenPdoMappingAndAutoOp()
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
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.
../src/MotionCode.c
../src/MotionCode.c motionCode_notification()
The functions that activate PDO mapping, Auto-Op and/or Hearbeat are then called if this flag is true:
../src/MotionCode.c motionCode_main()
while(true) // .. do not
execute the MotionCode ..
{
motionCodeFunctionLib_checkMotionParameterStoreCmdExtended(motionParameter.motionParameterStoreCmd); // ..
just check motionParameterStoreCmd
}
}
else // Else (If
MotionCode is not executed the first time) ..
{
while(true) // .. while
MotionCode is running ..
{
motionCodeFunctionLib_checkMotionParameterStoreCmdExtended(motionParameter.motionParameterStoreCmd); // ..
check motionParameterStoreCmd
stateControl(); // .. .. call
state Control
stateFunction(); // .. .. call
state machine
}
}
}
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
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
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:
../src/MotionCode.c stateControl()
In this stateStartMoving() the movement is started. In addition, the stateWaitForPosReached() is specified as the
next state:
../src/MotionCode.c stateStartMoving()
programSpecificFunctions_doRelPos(motionParameter.targetPosition,
motionParameter.targetVelocity);// Do relative positioning on TargetPosition with TargetVelocity
*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
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()
uint32_t actualStatusRegister = 0;
drive->readUi32(DEVICE_StatusRegister, &actualStatusRegister); // Read actual
value of DEVICE_StatusRegister
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()
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
;
}
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()
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
Passing the startTime is only necessary if the first pulse must have the correct period. Otherwise a 0 can simply be passed.
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:
uint8_t uint8_Variable = 8;
motionParameter.debug2 = (int32_t)(uint8_Variable); // convert uint8_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.
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()
../src/MotionCode.c stateControl()
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.
../src/MotionCode.c
Drive Assistant 5
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.
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:
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
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.
Before the debug session could be started, the following steps must be completed:
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
2
1
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.
1.
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 .
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.
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.
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
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.
Resume
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
Enable instruction stepping mode to examine a program as it steps into disassembled code.
Switch-on sequence
yes
MotionCode available?
no
motionCode_init()
Inizialise Communication
yes
Has CRC of MotionCode...
no
motionCode_notification...
Executing tasks
yes
MotionCode available?
no
motionCode_main()...
Module: MotionCode.c
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.
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
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);
void void -
void
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:
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 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
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
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
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
void setNotStorableDefaultValues(void);
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);
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;
}
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:
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.
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:
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.
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:
input uint8 -
uint8
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.
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
drive->memory[0]->i32
Data types:
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:
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!
drive->storeExtended(0xFFFFFFu, 0xFFFFFFu,
0xFFFFFFu, 0xFFFFFFu);
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:
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!
drive->restoreExtended(0xFFFFFFu, 0xFFFFFFu,
0xFFFFFFu, 0xFFFFFFu);
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:
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
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.
Function: Read
The "read" function can be used to read out a parameter from the object directory of the motor.
Declaration:
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
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.
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:
drive->watchdogTimerSet(2000);
This example shows how the WatchdogTimer is set to zero to disable it:
drive->watchdogTimerSet(0);
Info
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:
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:
timeDelay Uint32_t Time difference after which the value "true" is returned [μs]
if(startTime ==
0) // If state is called
first time ..
drive->readUi32(DEVICE_Timer, &startTime); // .. start timer
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
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]
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
../src/MotionCode.c motionCode_main
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:
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 !
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)
The values apply regardless of the motor/controller (BGE5510, BG66, BG75, BG95, ...).
The ROM stores the compiled MotionCode and read-only data. Read-only data means for example the initial value of a
variable:
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:
Largest MotionCode written so far with 2263 program lines occupies 47900 bytes 73 % 37 %
(Comparable MPU had needed 100% MPU memory at that time)
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.
Usable RAM for variables when all motion parameters are defined 652 Byte (163 32bit variables) 4748 Byte (1187 32bit variables)
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:
The .text segment contains code and read only data, which are placed in the ROM.
The segment .data contains all initialized global variables, which are placed in RAM.
The segment .bss contains all uninitialized or zero-initialized global variables which are placed in RAM.
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.
The segment .data contains all initialized global variables, which are placed in RAM.
The segment .bss contains all uninitialized or zero-initialized global variables which are placed in RAM.
Thus the template (V 2.03) occupies 20968 bytes in ROM and 4572 bytes in RAM (1228 + 3344).
-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
-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.
-6010 A read or write function of the drive interface was called with a NULL pointer as argument.
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).
1.4.1 Version
This document was created on the basis of the following versions:
Module Version
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:
If an older project is included into a newer MotionCode IDE version the following includes do not work:
Include path:
"${eclipse_home}/dunkermotoren/MotionCodeLibrary/${MOTIONCODE_LIBRARY_VERSION}/inc"
Include path:
Librarie:
MotionCodeFunctionLib
Include path:
"${eclipse_home}/dunkermotoren/MotionCodeLibrary/MotionCodeFunctionLibrary/$
{MOTIONCODE_FUNCTIONLIBRARY_VERSION}"
This is fixed in version 0002.00.0. Change the used version in the build variables:
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:
motionCodeFunctionLib_checkMotionParameterStoreCmdExtended(int32_t actStoreCmd);
Change in the build variables to this version (or newer) and use the new function in MotionCode_main() :
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:
Include paths:
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
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:
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!):
Otherwise there can be some problems in the background while the build process.
drive->writeUi32(0x490108, 14400);