-
Notifications
You must be signed in to change notification settings - Fork 3
/
Copy pathmd_demo_2README.html
168 lines (166 loc) · 15.9 KB
/
md_demo_2README.html
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "https://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" lang="en-US">
<head>
<meta http-equiv="Content-Type" content="text/xhtml;charset=UTF-8"/>
<meta http-equiv="X-UA-Compatible" content="IE=11"/>
<meta name="generator" content="Doxygen 1.11.0"/>
<meta name="viewport" content="width=device-width, initial-scale=1"/>
<title>CANopenDemo: CANopen demoDevice</title>
<link rel="icon" href="CANopenNode.png" type="image/x-icon" />
<link href="tabs.css" rel="stylesheet" type="text/css"/>
<script type="text/javascript" src="jquery.js"></script>
<script type="text/javascript" src="dynsections.js"></script>
<script type="text/javascript" src="clipboard.js"></script>
<link href="navtree.css" rel="stylesheet" type="text/css"/>
<script type="text/javascript" src="resize.js"></script>
<script type="text/javascript" src="cookie.js"></script>
<link href="search/search.css" rel="stylesheet" type="text/css"/>
<script type="text/javascript" src="search/searchdata.js"></script>
<script type="text/javascript" src="search/search.js"></script>
<link href="doxygen.css" rel="stylesheet" type="text/css" />
</head>
<body>
<div id="top"><!-- do not remove this div, it is closed by doxygen! -->
<div id="titlearea">
<table cellspacing="0" cellpadding="0">
<tbody>
<tr id="projectrow">
<td id="projectlogo"><img alt="Logo" src="CANopenNode.png"/></td>
<td id="projectalign">
<div id="projectname">CANopenDemo
</div>
<div id="projectbrief">CANopenNode demo, tutorial and testing</div>
</td>
</tr>
</tbody>
</table>
</div>
<!-- end header part -->
<!-- Generated by Doxygen 1.11.0 -->
<script type="text/javascript">
/* @license magnet:?xt=urn:btih:d3d9a9a6595521f9666a5e94cc830dab83b65699&dn=expat.txt MIT */
var searchBox = new SearchBox("searchBox", "search/",'.html');
/* @license-end */
</script>
<script type="text/javascript">
/* @license magnet:?xt=urn:btih:d3d9a9a6595521f9666a5e94cc830dab83b65699&dn=expat.txt MIT */
$(function() { codefold.init(0); });
/* @license-end */
</script>
<script type="text/javascript" src="menudata.js"></script>
<script type="text/javascript" src="menu.js"></script>
<script type="text/javascript">
/* @license magnet:?xt=urn:btih:d3d9a9a6595521f9666a5e94cc830dab83b65699&dn=expat.txt MIT */
$(function() {
initMenu('',true,false,'search.php','Search',false);
$(function() { init_search(); });
});
/* @license-end */
</script>
<div id="main-nav"></div>
<script type="text/javascript">
/* @license magnet:?xt=urn:btih:d3d9a9a6595521f9666a5e94cc830dab83b65699&dn=expat.txt MIT */
$(function(){ initResizable(false); });
/* @license-end */
</script>
<!-- window showing the filter options -->
<div id="MSearchSelectWindow"
onmouseover="return searchBox.OnSearchSelectShow()"
onmouseout="return searchBox.OnSearchSelectHide()"
onkeydown="return searchBox.OnSearchSelectKey(event)">
</div>
<!-- iframe showing the search results (closed by default) -->
<div id="MSearchResultsWindow">
<div id="MSearchResults">
<div class="SRPage">
<div id="SRIndex">
<div id="SRResults"></div>
<div class="SRStatus" id="Loading">Loading...</div>
<div class="SRStatus" id="Searching">Searching...</div>
<div class="SRStatus" id="NoMatches">No Matches</div>
</div>
</div>
</div>
</div>
</div><!-- top -->
<div id="doc-content">
<div><div class="header">
<div class="headertitle"><div class="title">CANopen demoDevice</div></div>
</div><!--header-->
<div class="contents">
<div class="textblock"><p>Demonstration of CANopen device based on <a href="https://github.com/CANopenNode/CANopenNode">CANopenNode</a>, which is free and open source CANopen Stack, based on (<a href="http://can-cia.org/standardization/technical-documents">CiA301</a>) standard.</p>
<p>demoDevice can run on different target devices. It contains object dictionary with most common communication parameters and some additional manufacturer specific and device profile parameters. Simple example program run from application interface and shows some principles of CANopenNode usage.</p>
<h1><a class="anchor" id="autotoc_md65"></a>
Object Dictionary</h1>
<p>Object Dictionary is central part of CANopen device. It contains well structured communication, manufacturer specific or standardized device profile parameters, accessible by different types of communication. See picture below or complete OD documentation in <a class="el" href="md_demo_2demoDevice.html">demoDevice.md</a>. Note also project file <code>demoDevice.xdd</code>, which can be opened and edited with EDSEditor.exe (Linux or Windows application). EDSEditor can export other files, including <a class="el" href="OD_8h_source.html">OD.h</a> and OD.c source files for this example. <code>demoDevice.xdd</code> and <code>demoDevice.eds</code> are standard CANopen device description files and can be opened also with other CANopen tools.</p>
<div class="image">
<img src="demoDevice.png" alt=""/>
<div class="caption">
EDSEditor</div></div>
<h1><a class="anchor" id="autotoc_md66"></a>
Application interface</h1>
<p>Entry point into the program is similar to Arduino, extended with CANopen and additional real-time thread. It is similar for all target devices. There are several functions, which are called from main or realtime thread: <a class="elRef" href="CANopenLinux/group__CO__applicationLinux.html#gaa775827cb85918843afe7ed64a5c5380">app_programStart()</a>, <a class="elRef" href="CANopenLinux/group__CO__applicationLinux.html#gad8db6074573590def9cdacf72d62274e">app_communicationReset()</a>, <a class="elRef" href="CANopenLinux/group__CO__applicationLinux.html#gaed23d85027aa8743ebc8435e9f211fc0">app_programEnd()</a>, <a class="elRef" href="CANopenLinux/group__CO__applicationLinux.html#ga4acab7f1f5515ae79d431c553240e42f">app_programAsync()</a> and <a class="elRef" href="CANopenLinux/group__CO__applicationLinux.html#ga9781581db25c53072204d12bc432b498">app_programRt()</a>. For details see <code>CANopenLinux/CO_application.h</code>. All code must be non-blocking. Application interface for demoDevice is in <code>CO_application.c</code> and contains calls to other examples.</p>
<h2><a class="anchor" id="autotoc_md67"></a>
Using global variables directly from Object Dictionary</h2>
<p>See <code><a class="el" href="OD_8h_source.html">OD.h</a></code> for several structures with OD variables. Structures are also used as data blocks, which can be stored into non-volatile memory on SDO command or automatically. Here is example of OD variable, which is incremented on program startup and is stored automatically: </p><pre class="fragment">OD_PERSIST_APP_AUTO.x2106_power_onCounter ++;
</pre><h2><a class="anchor" id="autotoc_md68"></a>
Object oriented access to the OD variable.</h2>
<p><code>objectAssessOD.h</code> and .c files contain example of programming style, which is used in all CANopenNode objects. No global variables are used, all used parameters are specified by <code><a class="el" href="structobjectAccessOD__t.html" title="Object declaration for objectAccessOD.">objectAccessOD_t</a></code> structure. One or multiple objects of type <code><a class="el" href="structobjectAccessOD__t.html" title="Object declaration for objectAccessOD.">objectAccessOD_t</a></code> are defined externally. This object is also passed as a first argument to all functions inside <code>objectAssessOD.h</code>.</p>
<h3><a class="anchor" id="autotoc_md69"></a>
Initialization of the object</h3>
<p>Object is initialized by <code>objectAccessOD_init()</code> function. Function accepts second argument <code><a class="elRef" href="CANopenNode/structOD__entry__t.html">OD_entry_t</a> *OD_demoRecord</code>, which is entry from Object Dictionary with specified index. In our case it is <code>Demo record</code> at index 0x2120, which contains several different sub-entries (see picture above). This OD entry is extended with own IO access functions (<code>OD_read_demoRecord</code> and <code>OD_write_demoRecord</code>). This means, that every read (SDO, PDO or application) will use our access functions and not the original. (Original access functions reads from or writes to the original memory location, specified by the Object Dictionary.)</p>
<h3><a class="anchor" id="autotoc_md70"></a>
OD_demoRecord</h3>
<p>Subindexes 1 to 4 of the OD_demoRecord contain four "exotic" variables, which can be SDO read, SDO written, or mapped to RPDO or TPDO. They have default value, which is stored in the original memory location. Our IO access functions just redirects to the original access functions, when accessing those subindexes. In initialization phase pointers to those variables are stored for later calculations.</p>
<p>Subindex 5 contains "Average of four numbers". This is read-only parameter and is calculated as average number from subindexes 0..4. In Object Dictionary it does not have default value, so Object Dictionary does not assign memory location for it. Its value is calculated directly inside <code>OD_read_demoRecord()</code> function at the moment, it is read (by SDO, TPDO or application). Function <a class="el" href="objectAccessOD_8h.html#af1f8acfa751e1133170031410cc66340" title="Read "average" variable from Object Dictionary.">objectAccessOD_readAverage()</a> can be used by application for that purpose.</p>
<p>Subindex 6 contains "Parameter with default value". It is meant as parameter for our application, which configures our <code>internalParameter</code>. Lets say, our <code>internalParameter</code> has units micrometers and "Parameter with default value" has units millimeters. In the initialization phase "Parameter with default value" is read and <code>internalParameter</code> is calculated from it. In <code>OD_read_demoRecord</code> <code>internalParameter</code> is scaled to millimeters and copied to buffer. In <code>OD_write_demoRecord</code> value from buffer is scaled to micrometers and written to <code>internalParameter</code>. In addition <code><a class="elRef" href="CANopenNode/group__CO__ODinterface.html#ga48eddfc4bb2d9e265eeb645706bfa01a">OD_writeOriginal()</a></code> is called, which writes the value also to the original memory location, specified by the Object Dictionary. This is necessary for storage to work.</p>
<p>All values from the OD_demoRecord (except subindex 5) are part of the <code>OD_PERSIST_APP</code> structure (see file <code><a class="el" href="OD_8h_source.html">OD.h</a></code>). This structure is added to the storage module (see file <code>CO_driver_custom.h</code>). If any of the values from the OD_demoRecord changes and storage is requested by SDO write (to 0x1010,5 in our case), then values are preserved and are available on the next power-on cycle.</p>
<h2><a class="anchor" id="autotoc_md71"></a>
Device identification</h2>
<p><code><a class="el" href="CO__identificators_8h.html" title="Device identificators for CANopenNode.">CO_identificators.h</a></code> and .c files contain configuration of CAN bitRate and CANopen nodeId and OD objects 0x1008(manufacturerDeviceName), 0x1009(manufacturerHardwareVersion), 0x100A(manufacturerSoftwareVersion) and 0x1018(identity). <code>CO_identificators_init()</code> adds simple OD_extensions to objects containing strings, fills identity values and sets initial values to unconfigured nodeId and bitRate.</p>
<p>Global variables and definitions from <code><a class="el" href="OD_8h_source.html">OD.h</a></code> are used, which is most simple and good enough in some cases.</p>
<h2><a class="anchor" id="autotoc_md72"></a>
Domain demo</h2>
<p><code><a class="el" href="domainDemo_8h.html" title="Example access to the Object Dictionary variable of type domain.">domainDemo.h</a></code> and .c files contain simplified example for CANopen domain data type. With this data type an arbitrary amount of data can be transferred. <code><a class="el" href="domainDemo_8c.html#aa2ecfa883a7b3bff5ebad41ed53c1e20" title="Initialize domainDemo object.">domainDemo_init()</a></code> adds extension to <code>OD_ENTRY_H2122_demoDomain</code> with own <code>OD_read_domainDemo</code> and <code>OD_write_domainDemo</code> functions. If data size transferred is larger than internal buffer, then those two functions are called several times during SDO data transfer.</p>
<h3><a class="anchor" id="autotoc_md73"></a>
Reading principle for demonstration</h3>
<p>Internal variable <code>dataSize</code> configures size of data to be transferred from the device. First data byte transferred has value 0, next 1 and so on sequentially to 255. Next value is 0, then 1 and so on up to <code>dataSize</code> bytes transferred.</p>
<h3><a class="anchor" id="autotoc_md74"></a>
Writing principle for demonstration</h3>
<p>Data bytes are received into device, any number of them. For demonstration purposed data bytes are verified: they must be in sequence 0, 1, ..., 255, 0, 1, ... If not, SDO is aborted. If transfer is successfully finished then internal variable <code>dataSize</code> is set to number of data bytes transferred.</p>
<h2><a class="anchor" id="autotoc_md75"></a>
Detecting change of state of the OD variable and request TPDO, to which OD variable is mapped</h2>
<p>In the example we detect change of state of the OD variable (TPDO COS functionality).</p>
<p><code>CO_application.c</code> shows the principle. In configuration phase extension is added to the OD entry with <code><a class="elRef" href="CANopenNode/group__CO__ODinterface.html#ga41c96feee5da30cd9117a35a307b96e1">OD_extension_init()</a></code>.</p>
<p>Inside <code><a class="elRef" href="CANopenLinux/group__CO__applicationLinux.html#ga9781581db25c53072204d12bc432b498">app_programRt()</a></code> function <code><a class="elRef" href="CANopenNode/group__CO__ODinterface.html#ga04808fe9528409e02ca78ff7a4fbee58">OD_requestTPDO()</a></code> is called on OD variables, when necessary.</p>
<p>If OD variable is mapped to any event triggered TPDO, then TPDO will be automatically sent, as specified in its communication parameters.</p>
<h1><a class="anchor" id="autotoc_md76"></a>
Run in Linux</h1>
<p>See CANopenLinux/README.md</p>
<p>By default program is compiled without gateway and in double threaded operation (mainline and RT thread). Macro <code>CO_DRIVER_CUSTOM</code> is defined, which includes <code>CO_driver_custom.h</code> into the foundation of all source files.</p>
<p>Note that several <code>*.persist</code> files are created in directory, from which <code>demoLinuxDevice</code> runs. These are files, which stores data blocks (from Object Dictionary). Directory for storage files can also be specified by program arguments. Each CANopen Linux device must use own directory for storage files. </p><pre class="fragment">cd demo
make
./demoLinuxDevice can0 -i 4
</pre><h1><a class="anchor" id="autotoc_md77"></a>
Run in PIC32</h1>
<p>See CANopenPIC/README.md</p>
<p>Program runs in Arduino style <a href="https://reference.digilentinc.com/reference/microprocessor/max32/start">Max32 board</a> with <a href="https://www.microchip.com/wwwproducts/en/PIC32MX795F512L">PIC32MX795F512L</a> Microcontroller or in Explorer16 board. Prepare device as specified in CANopenPIC/README.md. Load demoDevice program, and connect to CANopen Network. Device runs with 250kbps with NodeId=4. First initialize the eeprom: </p><pre class="fragment">cocomm "4 w 0x1011 1 vs load"
cocomm "4 reset node"
cocomm "4 w 0x1010 1 vs save"
cocomm "4 reset node"
</pre><p> Device has some peripherals enabled by default:</p><ul>
<li>chipKIT Pins 0..7 are used as digital inputs, TPDO1 sends them on change-of-state.</li>
<li>chipKIT Pins A0..A15 are used as analog inputs, TPDO2 sends four of them if event timer is configured (<code>cocomm "4 w 0x1801 5 u16 500"</code>).</li>
</ul>
<h1><a class="anchor" id="autotoc_md78"></a>
Testing with SDO and PDO</h1>
<p>See <a class="el" href="md_tutorial_2README.html">tutorial/README.md</a>, chapter Next steps. </p>
</div></div><!-- contents -->
</div><!-- PageDoc -->
<!-- start footer part -->
<hr class="footer"/><address class="footer"><small>
Generated by <a href="https://www.doxygen.org/index.html"><img class="footer" src="doxygen.svg" width="104" height="31" alt="doxygen"/></a> 1.11.0
</small></address>
</div><!-- doc-content -->
</body>
</html>