summaryrefslogtreecommitdiffstats
path: root/embedded.html
blob: 5194c15046b97f43d0f6282848bc308ccfd7427f (plain)
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
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
<!-- HTML header for doxygen 1.8.8-->
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
    <head>
        <meta http-equiv="X-UA-Compatible" content="IE=edge">
        <!-- For Mobile Devices -->
        <meta name="viewport" content="width=device-width, initial-scale=1">
        <meta http-equiv="Content-Type" content="text/xhtml;charset=UTF-8"/>
        <meta name="generator" content="Doxygen 1.8.10"/>
        <script type="text/javascript" src="https://code.jquery.com/jquery-2.1.1.min.js"></script>
        <title>uSCXML: SCXML on an ATMega328</title>
        <!--<link href="tabs.css" rel="stylesheet" type="text/css"/>-->
        <script type="text/javascript" src="dynsections.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>
<script type="text/javascript">
  $(document).ready(function() { init_search(); });
</script>
        <link href='https://fonts.googleapis.com/css?family=Roboto+Slab' rel='stylesheet' type='text/css'>
        <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.1/css/bootstrap.min.css">
        <link href="doxygen.css" rel="stylesheet" type="text/css" />
        <link href="customdoxygen.css" rel="stylesheet" type="text/css"/>
        <script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.1/js/bootstrap.min.js"></script>
        <script type="text/javascript" src="doxy-boot.js"></script>
    </head>
    <body>
        <nav class="navbar navbar-default" role="navigation">
            <div class="container">
                <div class="navbar-header">
                    <a class="navbar-brand">uSCXML 2.0.0</a>
                </div>
            </div>
        </nav>
        <div id="top"><!-- do not remove this div, it is closed by doxygen! -->
            <div class="content" id="content">
                <div class="container">
                    <div class="row">
                        <div class="col-sm-12 panel " style="padding-bottom: 15px;">
                            <div style="margin-bottom: 15px;">
<!-- end header part --><!-- Generated by Doxygen 1.8.10 -->
<script type="text/javascript">
var searchBox = new SearchBox("searchBox", "search",false,'Search');
</script>
  <div id="navrow1" class="tabs">
    <ul class="tablist">
      <li><a href="index.html"><span>Main&#160;Page</span></a></li>
      <li class="current"><a href="pages.html"><span>Related&#160;Pages</span></a></li>
      <li><a href="modules.html"><span>Modules</span></a></li>
      <li><a href="annotated.html"><span>Classes</span></a></li>
      <li><a href="files.html"><span>Files</span></a></li>
      <li>
        <div id="MSearchBox" class="MSearchBoxInactive">
        <span class="left">
          <img id="MSearchSelect" src="search/mag_sel.png"
               onmouseover="return searchBox.OnSearchSelectShow()"
               onmouseout="return searchBox.OnSearchSelectHide()"
               alt=""/>
          <input type="text" id="MSearchField" value="Search" accesskey="S"
               onfocus="searchBox.OnSearchFieldFocus(true)" 
               onblur="searchBox.OnSearchFieldFocus(false)" 
               onkeyup="searchBox.OnSearchFieldChange(event)"/>
          </span><span class="right">
            <a id="MSearchClose" href="javascript:searchBox.CloseResultsWindow()"><img id="MSearchCloseImg" border="0" src="search/close.png" alt=""/></a>
          </span>
        </div>
      </li>
    </ul>
  </div>
<!-- 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">
<iframe src="javascript:void(0)" frameborder="0" 
        name="MSearchResults" id="MSearchResults">
</iframe>
</div>

</div><!-- top -->
<div class="header">
  <div class="headertitle">
<div class="title">SCXML on an ATMega328 </div>  </div>
</div><!--header-->
<div class="contents">
<div class="toc"><h3>Table of Contents</h3>
<ul><li class="level1"><a href="#platform">Hardware Platform</a><ul><li class="level2"><a href="#sensors">Sensors</a></li>
<li class="level2"><a href="#actuators">Actuators</a></li>
</ul>
</li>
<li class="level1"><a href="#control_logic">Control Logic</a></li>
<li class="level1"><a href="#resources">Resources</a></li>
</ul>
</div>
<div class="textblock"><p>This page describes how to use SCXML to model the control flow for an embedded micro-controller. We will transform an SCXML state-chart onto ANSI-C, provide some scaffolding and deploy it onto the Arduino Nano. Regardless of the target platform, the approach is the same if you like to use the ANSI-C transformation for just any other platform.</p>
<h1><a class="anchor" id="platform"></a>
Hardware Platform</h1>
<p>For a project of mine, I used a solar-powered Arduino Nano to control four aquarium pumps to water my balcony plants when their soil is dry. There are some peculiarities that justify to use a state-chart to model the controller's behavior, namely:</p>
<ol type="1">
<li>There is only enough power for one pump at a time</li>
<li>Pumps should only run if there is sufficient sunlight</li>
<li>The pump related to the sensor with the driest soil below a given threshold should run</li>
<li>If a pump runs, it ought to run for a given minimum amount of time</li>
</ol>
<p>The whole system is powered via a 5W solar module, which is connected via a 12V DCDC converter to another 12V5V DCDC converter, allowing to operate the actuators with 12V and the Arduino with 5V. On the 12V potential, there are some gold caps worth ~150mF to stabilize the potential and provide some <em>kick-off</em> current for a pump to start.</p>
<h2><a class="anchor" id="sensors"></a>
Sensors</h2>
<p>In order to measure the soil's moisture, I originally bought those cheap moisture sensors that will measure conductivity between two zinc plated conductors. The problem with these is that they corrode pretty quickly. You can alleviate the problem somewhat by measuring only once every N minutes, but still I disliked the approach.</p>
<p>That's why I went for capacitive sensors with some nice aluminum plates that I can either drop into the water reservoir of my balcony's flower beds or bury at the edge of a bed. Moist soil will cause a higher capacity and we can measure it very easily with two digital pins on the ATMega328: Just set the first pin to <code>HIGH</code> and measure the time it takes for a second pin, connected to the same potential to read <code>HIGH</code>. The longer it took to achieve the <code>HIGH</code> potential on the second pin, the higher the capacity, the more moist the soil.</p>
<p>There is another sensor as a simple voltage divider with 1M Ohm and 100K Ohm to measure the voltage at the solar module. This will allow us only to water plants when the sun is actually shining and with sufficient strength.</p>
<h2><a class="anchor" id="actuators"></a>
Actuators</h2>
<p>I connected four 3W aquarium pumps via relais that I supply with 12V from the solar module and control via analog outputs from the Arduino as most digital outputs are taken by the capacitive sensors for the soil's moisture. The pumps are submerged in a 60l tank of water that I have to refill occasionally.</p>
<h1><a class="anchor" id="control_logic"></a>
Control Logic</h1>
<p>Initially, I developed the system as a pet project but soon realized that I could utilize a state-chart to, more formally, adhere to the requirements above. Here is the SCXML document I wrote:</p>
<div class="fragment"><div class="line"><a name="l00001"></a><span class="lineno">    1</span>&#160;&lt;scxml datamodel=&quot;native&quot; initial=&quot;dark&quot; version=&quot;1.0&quot;&gt;</div>
<div class="line"><a name="l00002"></a><span class="lineno">    2</span>&#160;  &lt;!-- we provide the datamodel inline in the scaffolding --&gt;</div>
<div class="line"><a name="l00003"></a><span class="lineno">    3</span>&#160;  &lt;script&gt;&lt;![CDATA[</div>
<div class="line"><a name="l00004"></a><span class="lineno">    4</span>&#160;    pinMode(LED, OUTPUT);</div>
<div class="line"><a name="l00005"></a><span class="lineno">    5</span>&#160;    for (char i = 0; i &lt; 4; ++i) {</div>
<div class="line"><a name="l00006"></a><span class="lineno">    6</span>&#160;      pinMode(pump[i], OUTPUT);</div>
<div class="line"><a name="l00007"></a><span class="lineno">    7</span>&#160;      digitalWrite(pump[i], PUMP_OFF);</div>
<div class="line"><a name="l00008"></a><span class="lineno">    8</span>&#160;      bed[i].set_CS_AutocaL_Millis(0xFFFFFFFF);</div>
<div class="line"><a name="l00009"></a><span class="lineno">    9</span>&#160;    }</div>
<div class="line"><a name="l00010"></a><span class="lineno">   10</span>&#160;  ]]&gt;&lt;/script&gt;</div>
<div class="line"><a name="l00011"></a><span class="lineno">   11</span>&#160;</div>
<div class="line"><a name="l00012"></a><span class="lineno">   12</span>&#160;  &lt;!-- it is too dark to water flowers --&gt;</div>
<div class="line"><a name="l00013"></a><span class="lineno">   13</span>&#160;  &lt;state id=&quot;dark&quot;&gt;</div>
<div class="line"><a name="l00014"></a><span class="lineno">   14</span>&#160;    &lt;transition event=&quot;light&quot; cond=&quot;_event-&gt;data.light &gt; LIGHT_THRES&quot; target=&quot;light&quot; /&gt;</div>
<div class="line"><a name="l00015"></a><span class="lineno">   15</span>&#160;    &lt;onentry&gt;</div>
<div class="line"><a name="l00016"></a><span class="lineno">   16</span>&#160;      &lt;script&gt;&lt;![CDATA[</div>
<div class="line"><a name="l00017"></a><span class="lineno">   17</span>&#160;        for (char i = 0; i &lt; 4; ++i) {</div>
<div class="line"><a name="l00018"></a><span class="lineno">   18</span>&#160;          digitalWrite(pump[i], PUMP_OFF);</div>
<div class="line"><a name="l00019"></a><span class="lineno">   19</span>&#160;        }</div>
<div class="line"><a name="l00020"></a><span class="lineno">   20</span>&#160;      ]]&gt;&lt;/script&gt;</div>
<div class="line"><a name="l00021"></a><span class="lineno">   21</span>&#160;    &lt;/onentry&gt;</div>
<div class="line"><a name="l00022"></a><span class="lineno">   22</span>&#160;  &lt;/state&gt;</div>
<div class="line"><a name="l00023"></a><span class="lineno">   23</span>&#160;</div>
<div class="line"><a name="l00024"></a><span class="lineno">   24</span>&#160;  &lt;!-- start to take measurements and activate single pumps if too dry --&gt;</div>
<div class="line"><a name="l00025"></a><span class="lineno">   25</span>&#160;  &lt;state id=&quot;light&quot;&gt;</div>
<div class="line"><a name="l00026"></a><span class="lineno">   26</span>&#160;    &lt;transition event=&quot;light&quot; cond=&quot;_event-&gt;data.light &amp;lt; LIGHT_THRES&quot; target=&quot;dark&quot; /&gt;</div>
<div class="line"><a name="l00027"></a><span class="lineno">   27</span>&#160;</div>
<div class="line"><a name="l00028"></a><span class="lineno">   28</span>&#160;    &lt;!-- delivers events for all the capsense measurements --&gt;</div>
<div class="line"><a name="l00029"></a><span class="lineno">   29</span>&#160;    &lt;invoke type=&quot;capsense&quot; id=&quot;cap&quot; /&gt;</div>
<div class="line"><a name="l00030"></a><span class="lineno">   30</span>&#160;</div>
<div class="line"><a name="l00031"></a><span class="lineno">   31</span>&#160;    &lt;state id=&quot;idle&quot;&gt;</div>
<div class="line"><a name="l00032"></a><span class="lineno">   32</span>&#160;      &lt;transition event=&quot;pump&quot; cond=&quot;soil[0] &amp;lt; 0 &amp;amp;&amp;amp;</div>
<div class="line"><a name="l00033"></a><span class="lineno">   33</span>&#160;                                     soil[0] &amp;lt;= soil[1] &amp;amp;&amp;amp;</div>
<div class="line"><a name="l00034"></a><span class="lineno">   34</span>&#160;                                     soil[0] &amp;lt;= soil[2] &amp;amp;&amp;amp;</div>
<div class="line"><a name="l00035"></a><span class="lineno">   35</span>&#160;                                     soil[0] &amp;lt;= soil[3]&quot; target=&quot;pump1&quot; /&gt;</div>
<div class="line"><a name="l00036"></a><span class="lineno">   36</span>&#160;      &lt;transition event=&quot;pump&quot; cond=&quot;soil[1] &amp;lt; 0 &amp;amp;&amp;amp;</div>
<div class="line"><a name="l00037"></a><span class="lineno">   37</span>&#160;                                     soil[1] &amp;lt;= soil[0] &amp;amp;&amp;amp;</div>
<div class="line"><a name="l00038"></a><span class="lineno">   38</span>&#160;                                     soil[1] &amp;lt;= soil[2] &amp;amp;&amp;amp;</div>
<div class="line"><a name="l00039"></a><span class="lineno">   39</span>&#160;                                     soil[1] &amp;lt;= soil[3]&quot; target=&quot;pump2&quot; /&gt;</div>
<div class="line"><a name="l00040"></a><span class="lineno">   40</span>&#160;      &lt;transition event=&quot;pump&quot; cond=&quot;soil[2] &amp;lt; 0 &amp;amp;&amp;amp;</div>
<div class="line"><a name="l00041"></a><span class="lineno">   41</span>&#160;                                     soil[2] &amp;lt;= soil[0] &amp;amp;&amp;amp;</div>
<div class="line"><a name="l00042"></a><span class="lineno">   42</span>&#160;                                     soil[2] &amp;lt;= soil[1] &amp;amp;&amp;amp;</div>
<div class="line"><a name="l00043"></a><span class="lineno">   43</span>&#160;                                     soil[2] &amp;lt;= soil[3]&quot; target=&quot;pump3&quot; /&gt;</div>
<div class="line"><a name="l00044"></a><span class="lineno">   44</span>&#160;      &lt;transition event=&quot;pump&quot; cond=&quot;soil[3] &amp;lt; 0 &amp;amp;&amp;amp;</div>
<div class="line"><a name="l00045"></a><span class="lineno">   45</span>&#160;                                     soil[3] &amp;lt;= soil[0] &amp;amp;&amp;amp;</div>
<div class="line"><a name="l00046"></a><span class="lineno">   46</span>&#160;                                     soil[3] &amp;lt;= soil[1] &amp;amp;&amp;amp;</div>
<div class="line"><a name="l00047"></a><span class="lineno">   47</span>&#160;                                     soil[3] &amp;lt;= soil[2]&quot; target=&quot;pump4&quot; /&gt;</div>
<div class="line"><a name="l00048"></a><span class="lineno">   48</span>&#160;    &lt;/state&gt;</div>
<div class="line"><a name="l00049"></a><span class="lineno">   49</span>&#160;    </div>
<div class="line"><a name="l00050"></a><span class="lineno">   50</span>&#160;    &lt;state id=&quot;pumping&quot;&gt;</div>
<div class="line"><a name="l00051"></a><span class="lineno">   51</span>&#160;      &lt;transition event=&quot;idle&quot; target=&quot;idle&quot; /&gt;</div>
<div class="line"><a name="l00052"></a><span class="lineno">   52</span>&#160;      &lt;onentry&gt;</div>
<div class="line"><a name="l00053"></a><span class="lineno">   53</span>&#160;        &lt;send delay=&quot;8000ms&quot; event=&quot;idle&quot; /&gt;</div>
<div class="line"><a name="l00054"></a><span class="lineno">   54</span>&#160;      &lt;/onentry&gt;</div>
<div class="line"><a name="l00055"></a><span class="lineno">   55</span>&#160;</div>
<div class="line"><a name="l00056"></a><span class="lineno">   56</span>&#160;      &lt;state id=&quot;pump1&quot;&gt;</div>
<div class="line"><a name="l00057"></a><span class="lineno">   57</span>&#160;        &lt;invoke type=&quot;pump&quot; id=&quot;1&quot; /&gt;</div>
<div class="line"><a name="l00058"></a><span class="lineno">   58</span>&#160;      &lt;/state&gt;</div>
<div class="line"><a name="l00059"></a><span class="lineno">   59</span>&#160;      &lt;state id=&quot;pump2&quot;&gt;</div>
<div class="line"><a name="l00060"></a><span class="lineno">   60</span>&#160;        &lt;invoke type=&quot;pump&quot; id=&quot;2&quot; /&gt;</div>
<div class="line"><a name="l00061"></a><span class="lineno">   61</span>&#160;      &lt;/state&gt;</div>
<div class="line"><a name="l00062"></a><span class="lineno">   62</span>&#160;      &lt;state id=&quot;pump3&quot;&gt;</div>
<div class="line"><a name="l00063"></a><span class="lineno">   63</span>&#160;        &lt;invoke type=&quot;pump&quot; id=&quot;3&quot; /&gt;</div>
<div class="line"><a name="l00064"></a><span class="lineno">   64</span>&#160;      &lt;/state&gt;</div>
<div class="line"><a name="l00065"></a><span class="lineno">   65</span>&#160;      &lt;state id=&quot;pump4&quot;&gt;</div>
<div class="line"><a name="l00066"></a><span class="lineno">   66</span>&#160;        &lt;invoke type=&quot;pump&quot; id=&quot;4&quot; /&gt;</div>
<div class="line"><a name="l00067"></a><span class="lineno">   67</span>&#160;      &lt;/state&gt;</div>
<div class="line"><a name="l00068"></a><span class="lineno">   68</span>&#160;    &lt;/state&gt;</div>
<div class="line"><a name="l00069"></a><span class="lineno">   69</span>&#160;  &lt;/state&gt;</div>
<div class="line"><a name="l00070"></a><span class="lineno">   70</span>&#160;&lt;/scxml&gt;</div>
</div><!-- fragment --><p>There are a few noteworthy things in the SCXML document above:</p>
<ul>
<li>Datamodel attribute is `native and no datamodel element is given<ul>
<li>This will cause the transpilation process to include all datamodel statements and expressions <em>as is</em> in the generated source, without passing them to a user-supplied callback for interpretation.</li>
<li>Using this approach, it is no longer possible to interpret the document with the browser.</li>
</ul>
</li>
<li>We can use identifiers and functions available on the Arduino platform<ul>
<li>As all expressions and statements will be inserted verbatim into the generated ANSI-C file, and will merely compile it as any other file when we deploy on the Arduino.</li>
</ul>
</li>
<li>Content of script elements is in CDATA sections while expressions in conditions are escaped<ul>
<li>We are using the <a href="https://github.com/tklab-tud/uscxml/blob/master/src/uscxml/util/DOM.cpp#L36">DOMLSSerializer</a> to create a textual representation of the XML DOM and I could not convince it to unescape XML entities when writing the stream.</li>
</ul>
</li>
<li>We assume a <code>pump</code> and a <code>capsense</code> invoker<ul>
<li>Indeed, we will not write proper invokers but just mock them in the scaffolding. The important thing is that we get the lifetime management from the SCXML semantics.</li>
</ul>
</li>
</ul>
<p>When we transform this document via <code>uscxml-transform -tc -i WaterPump.scxml -o stateMachine.c</code> we will arrive at a <a href="https://github.com/tklab-tud/uscxml/tree/master/apps/arduino/stateMachine.c">stateMachine.c file</a> which conforms to the control flow modeled in the SCXML file. Now, we will need to write the scaffolding that connects the callbacks and starts the machine. The complete scaffolding for the generated state machine is given below:</p>
<div class="fragment"><div class="line"><a name="l00001"></a><span class="lineno">    1</span>&#160;<span class="comment">// Resources:</span></div>
<div class="line"><a name="l00002"></a><span class="lineno">    2</span>&#160;<span class="comment">// https://www.avrprogrammers.com/howto/atmega328-power</span></div>
<div class="line"><a name="l00003"></a><span class="lineno">    3</span>&#160;<span class="comment">// https://github.com/PaulStoffregen/CapacitiveSensor</span></div>
<div class="line"><a name="l00004"></a><span class="lineno">    4</span>&#160;<span class="comment">// https://de.wikipedia.org/wiki/Faustformelverfahren_%28Automatisierungstechnik%29</span></div>
<div class="line"><a name="l00005"></a><span class="lineno">    5</span>&#160;<span class="comment">// http://brettbeauregard.com/blog/2011/04/improving-the-beginners-pid-introduction/</span></div>
<div class="line"><a name="l00006"></a><span class="lineno">    6</span>&#160;<span class="comment">// google://SCC3 for conformal coating</span></div>
<div class="line"><a name="l00007"></a><span class="lineno">    7</span>&#160;</div>
<div class="line"><a name="l00008"></a><span class="lineno">    8</span>&#160;<span class="preprocessor">#include &lt;LowPower.h&gt;</span> </div>
<div class="line"><a name="l00009"></a><span class="lineno">    9</span>&#160;<span class="preprocessor">#include &lt;CapacitiveSensor.h&gt;</span> </div>
<div class="line"><a name="l00010"></a><span class="lineno">   10</span>&#160;</div>
<div class="line"><a name="l00011"></a><span class="lineno">   11</span>&#160;</div>
<div class="line"><a name="l00012"></a><span class="lineno">   12</span>&#160;<span class="preprocessor">#define USCXML_NO_HISTORY</span></div>
<div class="line"><a name="l00013"></a><span class="lineno">   13</span>&#160;</div>
<div class="line"><a name="l00014"></a><span class="lineno">   14</span>&#160;<span class="preprocessor">#define LED 13                     // LED pin on the Arduino Nano</span></div>
<div class="line"><a name="l00015"></a><span class="lineno">   15</span>&#160;<span class="preprocessor">#define LIGHT A7                   // 1:10 voltage divider soldered into the solar panel</span></div>
<div class="line"><a name="l00016"></a><span class="lineno">   16</span>&#160;<span class="preprocessor">#define LIGHT_THRES 300            // do not actuate beneath this brightness</span></div>
<div class="line"><a name="l00017"></a><span class="lineno">   17</span>&#160;<span class="preprocessor">#define MEASURE_INTERVAL SLEEP_1S  // time between cycles</span></div>
<div class="line"><a name="l00018"></a><span class="lineno">   18</span>&#160;<span class="preprocessor">#define DARK_SLEEP_CYCLES 1</span></div>
<div class="line"><a name="l00019"></a><span class="lineno">   19</span>&#160;</div>
<div class="line"><a name="l00020"></a><span class="lineno">   20</span>&#160;<span class="preprocessor">#define PUMP_ON LOW                // Setting an output to LOW will trigger the relais</span></div>
<div class="line"><a name="l00021"></a><span class="lineno">   21</span>&#160;<span class="preprocessor">#define PUMP_OFF HIGH</span></div>
<div class="line"><a name="l00022"></a><span class="lineno">   22</span>&#160;</div>
<div class="line"><a name="l00023"></a><span class="lineno">   23</span>&#160;<span class="preprocessor">#define ROLLOFF 0.8                // exponential smoothing for sensor readings</span></div>
<div class="line"><a name="l00024"></a><span class="lineno">   24</span>&#160;</div>
<div class="line"><a name="l00025"></a><span class="lineno">   25</span>&#160;<span class="keywordtype">float</span> soil[4] = { 0, 0, 0, 0 };    <span class="comment">// smoothed sensor readings from the capacitive sensors</span></div>
<div class="line"><a name="l00026"></a><span class="lineno">   26</span>&#160;<span class="keywordtype">int</span> pump[4] = { A0, A1, A2, A3 };  <span class="comment">// we abuse analog pins as digital output</span></div>
<div class="line"><a name="l00027"></a><span class="lineno">   27</span>&#160;<span class="keywordtype">int</span> activePump = -1;</div>
<div class="line"><a name="l00028"></a><span class="lineno">   28</span>&#160;</div>
<div class="line"><a name="l00029"></a><span class="lineno">   29</span>&#160;<span class="keywordtype">int</span> thrs[4] = { 1400, 1400, 1400, 1400 }; <span class="comment">// start pumping below these values</span></div>
<div class="line"><a name="l00030"></a><span class="lineno">   30</span>&#160;</div>
<div class="line"><a name="l00031"></a><span class="lineno">   31</span>&#160;CapacitiveSensor bed[4] = {        <span class="comment">// Pins where the capacitive sensors are connected</span></div>
<div class="line"><a name="l00032"></a><span class="lineno">   32</span>&#160;  CapacitiveSensor(3, 2),</div>
<div class="line"><a name="l00033"></a><span class="lineno">   33</span>&#160;  CapacitiveSensor(5, 4),</div>
<div class="line"><a name="l00034"></a><span class="lineno">   34</span>&#160;  CapacitiveSensor(7, 6),</div>
<div class="line"><a name="l00035"></a><span class="lineno">   35</span>&#160;  CapacitiveSensor(9, 8)</div>
<div class="line"><a name="l00036"></a><span class="lineno">   36</span>&#160;};</div>
<div class="line"><a name="l00037"></a><span class="lineno">   37</span>&#160;<span class="keywordtype">char</span> readCapSense = 0;             <span class="comment">// Whether the capsense invoker is active</span></div>
<div class="line"><a name="l00038"></a><span class="lineno">   38</span>&#160;</div>
<div class="line"><a name="l00039"></a><span class="lineno">   39</span>&#160;<span class="keyword">struct </span>data_t {</div>
<div class="line"><a name="l00040"></a><span class="lineno">   40</span>&#160;  <span class="keywordtype">int</span> light;</div>
<div class="line"><a name="l00041"></a><span class="lineno">   41</span>&#160;};</div>
<div class="line"><a name="l00042"></a><span class="lineno">   42</span>&#160;<span class="keyword">struct </span>event_t {</div>
<div class="line"><a name="l00043"></a><span class="lineno">   43</span>&#160;  <span class="keyword">const</span> <span class="keywordtype">char</span>* name;</div>
<div class="line"><a name="l00044"></a><span class="lineno">   44</span>&#160;  <span class="keyword">struct </span>data_t data;</div>
<div class="line"><a name="l00045"></a><span class="lineno">   45</span>&#160;};</div>
<div class="line"><a name="l00046"></a><span class="lineno">   46</span>&#160;</div>
<div class="line"><a name="l00047"></a><span class="lineno">   47</span>&#160;<span class="comment">// the various events</span></div>
<div class="line"><a name="l00048"></a><span class="lineno">   48</span>&#160;<span class="keywordtype">long</span> pumpRemain = 0;</div>
<div class="line"><a name="l00049"></a><span class="lineno">   49</span>&#160;<span class="keyword">struct </span>event_t _eventIdle = {</div>
<div class="line"><a name="l00050"></a><span class="lineno">   50</span>&#160;  name: <span class="stringliteral">&quot;idle&quot;</span></div>
<div class="line"><a name="l00051"></a><span class="lineno">   51</span>&#160;};</div>
<div class="line"><a name="l00052"></a><span class="lineno">   52</span>&#160;<span class="keyword">struct </span>event_t _eventLight = {</div>
<div class="line"><a name="l00053"></a><span class="lineno">   53</span>&#160;  name: <span class="stringliteral">&quot;light&quot;</span></div>
<div class="line"><a name="l00054"></a><span class="lineno">   54</span>&#160;};</div>
<div class="line"><a name="l00055"></a><span class="lineno">   55</span>&#160;<span class="keyword">struct </span>event_t _eventPump = {</div>
<div class="line"><a name="l00056"></a><span class="lineno">   56</span>&#160;  name: <span class="stringliteral">&quot;pump&quot;</span></div>
<div class="line"><a name="l00057"></a><span class="lineno">   57</span>&#160;};</div>
<div class="line"><a name="l00058"></a><span class="lineno">   58</span>&#160;<span class="keyword">struct </span>event_t* _event;</div>
<div class="line"><a name="l00059"></a><span class="lineno">   59</span>&#160;</div>
<div class="line"><a name="l00060"></a><span class="lineno">   60</span>&#160;<span class="preprocessor">#include &quot;stateMachine.c&quot;</span></div>
<div class="line"><a name="l00061"></a><span class="lineno">   61</span>&#160;</div>
<div class="line"><a name="l00062"></a><span class="lineno">   62</span>&#160;<a class="code" href="structuscxml__ctx.html">uscxml_ctx</a> ctx;</div>
<div class="line"><a name="l00063"></a><span class="lineno">   63</span>&#160;</div>
<div class="line"><a name="l00064"></a><span class="lineno">   64</span>&#160;<span class="comment">/* state chart is invoking something */</span></div>
<div class="line"><a name="l00065"></a><span class="lineno">   65</span>&#160;<span class="keyword">static</span> <span class="keywordtype">int</span> invoke(<span class="keyword">const</span> <a class="code" href="structuscxml__ctx.html">uscxml_ctx</a>* ctx,</div>
<div class="line"><a name="l00066"></a><span class="lineno">   66</span>&#160;                  <span class="keyword">const</span> <a class="code" href="structuscxml__state.html">uscxml_state</a>* s,</div>
<div class="line"><a name="l00067"></a><span class="lineno">   67</span>&#160;                  <span class="keyword">const</span> <a class="code" href="structuscxml__elem__invoke.html">uscxml_elem_invoke</a>* invocation,</div>
<div class="line"><a name="l00068"></a><span class="lineno">   68</span>&#160;                  <span class="keywordtype">unsigned</span> <span class="keywordtype">char</span> uninvoke) {</div>
<div class="line"><a name="l00069"></a><span class="lineno">   69</span>&#160;  <span class="keywordflow">if</span> (strcmp(invocation-&gt;type, <span class="stringliteral">&quot;pump&quot;</span>) == 0) {</div>
<div class="line"><a name="l00070"></a><span class="lineno">   70</span>&#160;    <span class="keywordtype">int</span> pumpId = atoi(invocation-&gt;id);</div>
<div class="line"><a name="l00071"></a><span class="lineno">   71</span>&#160;    digitalWrite(pump[pumpId], uninvoke == 0 ? PUMP_ON : PUMP_OFF);</div>
<div class="line"><a name="l00072"></a><span class="lineno">   72</span>&#160;  } <span class="keywordflow">else</span> <span class="keywordflow">if</span> (strcmp(invocation-&gt;type, <span class="stringliteral">&quot;capsense&quot;</span>) == 0) {</div>
<div class="line"><a name="l00073"></a><span class="lineno">   73</span>&#160;    readCapSense = uninvoke;</div>
<div class="line"><a name="l00074"></a><span class="lineno">   74</span>&#160;  }</div>
<div class="line"><a name="l00075"></a><span class="lineno">   75</span>&#160;}</div>
<div class="line"><a name="l00076"></a><span class="lineno">   76</span>&#160;</div>
<div class="line"><a name="l00077"></a><span class="lineno">   77</span>&#160;<span class="comment">/* is the event matching */</span></div>
<div class="line"><a name="l00078"></a><span class="lineno">   78</span>&#160;<span class="keyword">static</span> <span class="keywordtype">int</span> matched(<span class="keyword">const</span> <a class="code" href="structuscxml__ctx.html">uscxml_ctx</a>* ctx,</div>
<div class="line"><a name="l00079"></a><span class="lineno">   79</span>&#160;                   <span class="keyword">const</span> <a class="code" href="structuscxml__transition.html">uscxml_transition</a>* transition,</div>
<div class="line"><a name="l00080"></a><span class="lineno">   80</span>&#160;                   <span class="keyword">const</span> <span class="keywordtype">void</span>* event) {</div>
<div class="line"><a name="l00081"></a><span class="lineno">   81</span>&#160;  <span class="comment">// we ignore most event name matching rules here</span></div>
<div class="line"><a name="l00082"></a><span class="lineno">   82</span>&#160;  <span class="keywordflow">return</span> strcmp(transition-&gt;event, ((<span class="keyword">const</span> <span class="keyword">struct</span> event_t*)event)-&gt;name) == 0;</div>
<div class="line"><a name="l00083"></a><span class="lineno">   83</span>&#160;}</div>
<div class="line"><a name="l00084"></a><span class="lineno">   84</span>&#160;</div>
<div class="line"><a name="l00085"></a><span class="lineno">   85</span>&#160;<span class="keyword">static</span> <span class="keywordtype">int</span> send(<span class="keyword">const</span> <a class="code" href="structuscxml__ctx.html">uscxml_ctx</a>* ctx, <span class="keyword">const</span> <a class="code" href="structuscxml__elem__send.html">uscxml_elem_send</a>* send) {</div>
<div class="line"><a name="l00086"></a><span class="lineno">   86</span>&#160;  <span class="keywordflow">if</span> (send-&gt;delay &gt; 0)</div>
<div class="line"><a name="l00087"></a><span class="lineno">   87</span>&#160;    pumpRemain = send-&gt;delay;</div>
<div class="line"><a name="l00088"></a><span class="lineno">   88</span>&#160;  <span class="keywordflow">return</span> USCXML_ERR_OK;</div>
<div class="line"><a name="l00089"></a><span class="lineno">   89</span>&#160;}</div>
<div class="line"><a name="l00090"></a><span class="lineno">   90</span>&#160;</div>
<div class="line"><a name="l00091"></a><span class="lineno">   91</span>&#160;<span class="keyword">static</span> <span class="keywordtype">void</span>* dequeueExternal(<span class="keyword">const</span> <a class="code" href="structuscxml__ctx.html">uscxml_ctx</a>* ctx) {</div>
<div class="line"><a name="l00092"></a><span class="lineno">   92</span>&#160;  <span class="comment">// we will only call step when we have an event</span></div>
<div class="line"><a name="l00093"></a><span class="lineno">   93</span>&#160;  <span class="keywordtype">void</span>* tmp = _event;</div>
<div class="line"><a name="l00094"></a><span class="lineno">   94</span>&#160;  _event = NULL;</div>
<div class="line"><a name="l00095"></a><span class="lineno">   95</span>&#160;  <span class="keywordflow">return</span> tmp;</div>
<div class="line"><a name="l00096"></a><span class="lineno">   96</span>&#160;}</div>
<div class="line"><a name="l00097"></a><span class="lineno">   97</span>&#160;</div>
<div class="line"><a name="l00098"></a><span class="lineno">   98</span>&#160;<span class="keyword">static</span> <span class="keywordtype">bool</span> isInState(<span class="keyword">const</span> <span class="keywordtype">char</span>* stateId) {</div>
<div class="line"><a name="l00099"></a><span class="lineno">   99</span>&#160;  <span class="keywordflow">for</span> (<span class="keywordtype">size_t</span> i = 0; i &lt; ctx.machine-&gt;nr_states; i++) {</div>
<div class="line"><a name="l00100"></a><span class="lineno">  100</span>&#160;    <span class="keywordflow">if</span> (ctx.machine-&gt;states[i].name &amp;&amp;</div>
<div class="line"><a name="l00101"></a><span class="lineno">  101</span>&#160;            strcmp(ctx.machine-&gt;states[i].name, stateId) == 0 &amp;&amp;</div>
<div class="line"><a name="l00102"></a><span class="lineno">  102</span>&#160;            BIT_HAS(i, ctx.config)) {</div>
<div class="line"><a name="l00103"></a><span class="lineno">  103</span>&#160;      <span class="keywordflow">return</span> <span class="keyword">true</span>;</div>
<div class="line"><a name="l00104"></a><span class="lineno">  104</span>&#160;    }</div>
<div class="line"><a name="l00105"></a><span class="lineno">  105</span>&#160;  }</div>
<div class="line"><a name="l00106"></a><span class="lineno">  106</span>&#160;</div>
<div class="line"><a name="l00107"></a><span class="lineno">  107</span>&#160;  <span class="keywordflow">return</span> <span class="keyword">false</span>;</div>
<div class="line"><a name="l00108"></a><span class="lineno">  108</span>&#160;}</div>
<div class="line"><a name="l00109"></a><span class="lineno">  109</span>&#160;</div>
<div class="line"><a name="l00110"></a><span class="lineno">  110</span>&#160;<span class="keywordtype">void</span> setup() {</div>
<div class="line"><a name="l00111"></a><span class="lineno">  111</span>&#160;  <span class="comment">// initilize the state chart</span></div>
<div class="line"><a name="l00112"></a><span class="lineno">  112</span>&#160;  memset(&amp;ctx, 0, <span class="keyword">sizeof</span>(<a class="code" href="structuscxml__ctx.html">uscxml_ctx</a>));</div>
<div class="line"><a name="l00113"></a><span class="lineno">  113</span>&#160;  ctx.machine = &amp;USCXML_MACHINE;</div>
<div class="line"><a name="l00114"></a><span class="lineno">  114</span>&#160;  ctx.invoke = invoke;</div>
<div class="line"><a name="l00115"></a><span class="lineno">  115</span>&#160;  ctx.is_matched = matched;</div>
<div class="line"><a name="l00116"></a><span class="lineno">  116</span>&#160;  ctx.dequeue_external = dequeueExternal;</div>
<div class="line"><a name="l00117"></a><span class="lineno">  117</span>&#160;  ctx.exec_content_send = send;</div>
<div class="line"><a name="l00118"></a><span class="lineno">  118</span>&#160;</div>
<div class="line"><a name="l00119"></a><span class="lineno">  119</span>&#160;  <span class="keywordtype">int</span> err = USCXML_ERR_OK;</div>
<div class="line"><a name="l00120"></a><span class="lineno">  120</span>&#160;</div>
<div class="line"><a name="l00121"></a><span class="lineno">  121</span>&#160;  <span class="comment">// run until first stable config</span></div>
<div class="line"><a name="l00122"></a><span class="lineno">  122</span>&#160;  <span class="keywordflow">while</span>((err = uscxml_step(&amp;ctx)) != USCXML_ERR_IDLE) {}</div>
<div class="line"><a name="l00123"></a><span class="lineno">  123</span>&#160;}</div>
<div class="line"><a name="l00124"></a><span class="lineno">  124</span>&#160;</div>
<div class="line"><a name="l00125"></a><span class="lineno">  125</span>&#160;</div>
<div class="line"><a name="l00126"></a><span class="lineno">  126</span>&#160;<span class="keywordtype">void</span> loop() {</div>
<div class="line"><a name="l00127"></a><span class="lineno">  127</span>&#160;  digitalWrite(LED, HIGH);</div>
<div class="line"><a name="l00128"></a><span class="lineno">  128</span>&#160;</div>
<div class="line"><a name="l00129"></a><span class="lineno">  129</span>&#160;  <span class="keywordtype">int</span> err = USCXML_ERR_OK;</div>
<div class="line"><a name="l00130"></a><span class="lineno">  130</span>&#160;</div>
<div class="line"><a name="l00131"></a><span class="lineno">  131</span>&#160;  <span class="keywordflow">if</span> (readCapSense) {</div>
<div class="line"><a name="l00132"></a><span class="lineno">  132</span>&#160;    <span class="comment">// capsense invoker is active</span></div>
<div class="line"><a name="l00133"></a><span class="lineno">  133</span>&#160;    <span class="keywordflow">for</span> (<span class="keywordtype">int</span> i = 0; i &lt; 4; ++i) {</div>
<div class="line"><a name="l00134"></a><span class="lineno">  134</span>&#160;      <span class="keywordtype">int</span> cap = bed[i].capacitiveSensor(50);</div>
<div class="line"><a name="l00135"></a><span class="lineno">  135</span>&#160;      <span class="keywordflow">if</span> (cap &gt; 0) {</div>
<div class="line"><a name="l00136"></a><span class="lineno">  136</span>&#160;        soil[i] = ROLLOFF * soil[i] + (1 - ROLLOFF) * (cap - thrs[i]);</div>
<div class="line"><a name="l00137"></a><span class="lineno">  137</span>&#160;      }</div>
<div class="line"><a name="l00138"></a><span class="lineno">  138</span>&#160;    }</div>
<div class="line"><a name="l00139"></a><span class="lineno">  139</span>&#160;  }</div>
<div class="line"><a name="l00140"></a><span class="lineno">  140</span>&#160;</div>
<div class="line"><a name="l00141"></a><span class="lineno">  141</span>&#160;  _eventLight.data.light = analogRead(LIGHT);</div>
<div class="line"><a name="l00142"></a><span class="lineno">  142</span>&#160;  _event = &amp;_eventLight;</div>
<div class="line"><a name="l00143"></a><span class="lineno">  143</span>&#160;  <span class="keywordflow">while</span>((err = uscxml_step(&amp;ctx)) != USCXML_ERR_IDLE) {}</div>
<div class="line"><a name="l00144"></a><span class="lineno">  144</span>&#160;</div>
<div class="line"><a name="l00145"></a><span class="lineno">  145</span>&#160;  <span class="keywordflow">if</span> (isInState(<span class="stringliteral">&quot;dark&quot;</span>)) {</div>
<div class="line"><a name="l00146"></a><span class="lineno">  146</span>&#160;    LowPower.powerDown(MEASURE_INTERVAL, ADC_OFF, BOD_OFF);</div>
<div class="line"><a name="l00147"></a><span class="lineno">  147</span>&#160;    <span class="keywordflow">return</span>;</div>
<div class="line"><a name="l00148"></a><span class="lineno">  148</span>&#160;  }</div>
<div class="line"><a name="l00149"></a><span class="lineno">  149</span>&#160;</div>
<div class="line"><a name="l00150"></a><span class="lineno">  150</span>&#160;  <span class="keywordflow">if</span> (isInState(<span class="stringliteral">&quot;light&quot;</span>)) {</div>
<div class="line"><a name="l00151"></a><span class="lineno">  151</span>&#160;    <span class="keywordflow">if</span> (<span class="keyword">false</span>) {</div>
<div class="line"><a name="l00152"></a><span class="lineno">  152</span>&#160;    } <span class="keywordflow">else</span> <span class="keywordflow">if</span> (isInState(<span class="stringliteral">&quot;pumping&quot;</span>)) {</div>
<div class="line"><a name="l00153"></a><span class="lineno">  153</span>&#160;      <span class="comment">// is time elapsed already?</span></div>
<div class="line"><a name="l00154"></a><span class="lineno">  154</span>&#160;      <span class="keywordflow">if</span> (pumpRemain == 0) {</div>
<div class="line"><a name="l00155"></a><span class="lineno">  155</span>&#160;        _event = &amp;_eventIdle;</div>
<div class="line"><a name="l00156"></a><span class="lineno">  156</span>&#160;        <span class="keywordflow">while</span>((err = uscxml_step(&amp;ctx)) != USCXML_ERR_IDLE) {}</div>
<div class="line"><a name="l00157"></a><span class="lineno">  157</span>&#160;      }</div>
<div class="line"><a name="l00158"></a><span class="lineno">  158</span>&#160;    } <span class="keywordflow">else</span> <span class="keywordflow">if</span> (isInState(<span class="stringliteral">&quot;idle&quot;</span>)) {</div>
<div class="line"><a name="l00159"></a><span class="lineno">  159</span>&#160;      <span class="comment">// check is we need to pump</span></div>
<div class="line"><a name="l00160"></a><span class="lineno">  160</span>&#160;      _event = &amp;_eventPump;</div>
<div class="line"><a name="l00161"></a><span class="lineno">  161</span>&#160;      <span class="keywordflow">while</span>((err = uscxml_step(&amp;ctx)) != USCXML_ERR_IDLE) {}</div>
<div class="line"><a name="l00162"></a><span class="lineno">  162</span>&#160;    }</div>
<div class="line"><a name="l00163"></a><span class="lineno">  163</span>&#160;  }</div>
<div class="line"><a name="l00164"></a><span class="lineno">  164</span>&#160;</div>
<div class="line"><a name="l00165"></a><span class="lineno">  165</span>&#160;  pumpRemain = (pumpRemain &gt;= 8000) ? pumpRemain - 8000 : 0;</div>
<div class="line"><a name="l00166"></a><span class="lineno">  166</span>&#160;</div>
<div class="line"><a name="l00167"></a><span class="lineno">  167</span>&#160;  digitalWrite(LED, LOW);</div>
<div class="line"><a name="l00168"></a><span class="lineno">  168</span>&#160;  LowPower.powerDown(MEASURE_INTERVAL, ADC_OFF, BOD_OFF);</div>
<div class="line"><a name="l00169"></a><span class="lineno">  169</span>&#160;</div>
<div class="line"><a name="l00170"></a><span class="lineno">  170</span>&#160;}</div>
<div class="ttc" id="structuscxml__transition_html"><div class="ttname"><a href="structuscxml__transition.html">uscxml_transition</a></div><div class="ttdoc">All information pertaining to a <transition> element. </div><div class="ttdef"><b>Definition:</b> stateMachine.c:250</div></div>
<div class="ttc" id="structuscxml__state_html"><div class="ttname"><a href="structuscxml__state.html">uscxml_state</a></div><div class="ttdoc">All information pertaining to any state element. </div><div class="ttdef"><b>Definition:</b> stateMachine.c:234</div></div>
<div class="ttc" id="structuscxml__elem__send_html"><div class="ttname"><a href="structuscxml__elem__send.html">uscxml_elem_send</a></div><div class="ttdoc">All information pertaining to a <send> element. </div><div class="ttdef"><b>Definition:</b> stateMachine.c:315</div></div>
<div class="ttc" id="structuscxml__ctx_html"><div class="ttname"><a href="structuscxml__ctx.html">uscxml_ctx</a></div><div class="ttdoc">Represents an instance of a state-chart at runtime/. </div><div class="ttdef"><b>Definition:</b> stateMachine.c:335</div></div>
<div class="ttc" id="structuscxml__elem__invoke_html"><div class="ttname"><a href="structuscxml__elem__invoke.html">uscxml_elem_invoke</a></div><div class="ttdoc">All information pertaining to an <invoke> element. </div><div class="ttdef"><b>Definition:</b> stateMachine.c:295</div></div>
</div><!-- fragment --><p>To integrate the scaffolding and the control logic from the state-chart, the generated <code>stateMachine.c</code> is merely included into the compilation unit. To compile it all, I am using <a href="http://platformio.org">PlatformIO</a> IDE as it is more convenient to work with multifile projects as apposed to the <a href="https://www.arduino.cc/en/Main/Software">Arduino IDE</a>, but both will work. It is important, not to compile <code>stateMachine.c</code> as a distinct compilation unit, but only as part of the scaffolding. If you have any problems to exclude it from the build process, you may always rename it into something without a <code>.c</code> extension.</p>
<p>The scaffolding is rather minimal and somewhat unorthodox as I tried to get away without using <code>malloc</code> for dynamic memory allocations, but keep everything on the stack. Let's walk through the individual lines:</p>
<ul>
<li>First we include the header files for <a href="https://github.com/rocketscream/Low-Power">LowPower</a> and <a href="https://github.com/PaulStoffregen/CapacitiveSensor">CapacitiveSensor</a>. With PlatformIO, you will have to copy them into your <code>lib</code> directory along with their respective implementations.</li>
<li>Then we declare some macros that define constant values. Noteworthy is the <code>USCXML_NO_HISTORY</code> macro which causes the generated ANSI-C to drop a block of code for processing history elements, which we do not use.</li>
<li>Afterwards, we declare and define variables. We could have them as part of a <code>datamodel</code> element in the original SCXML document, but in my opinion, defining them here makes their existence more explicit.</li>
<li>It is noteworthy that we do enumerate all the events we are going to pass and will not implement an actual queue of events. A proper queue would require malloc and there will never be more than one event to consider per microstep.</li>
<li>In line 62, we include the generated ANSI-C stateMachine and define a context, as it is required to represent the state of a state-chart.</li>
<li>Then we define the callbacks that we later connect to the state-chart's context:<ul>
<li><code>invoke</code> will be called whenever an invocation is to be started or stopped at the end of a macro-step. This is where we merely remember whether we are supposed to start a pump (type <code>pump</code>) or deliver sensor readings from the capacitive sensors (type <code>capsense</code>).</li>
<li><code>matched</code> is called to determine whether a given transition's event descriptor is matched by a given event and a concept explained in more detail in the SCXML recommendation. In this implementation, we ignore the finer points of event descriptor matching and only match, when the event's name is a literal match for the transition's event. attribute</li>
<li><code>send</code>: When we start a pump, we are sending a delayed event to ourselves which we will have to deliver back into the state-chart after the given time in milliseconds passed. We just remember the current delay in <code>pumpRemain</code> and, subsequently, decrease it until we reach the timeout and have to deliver it.</li>
<li><code>dequeueExternal</code>: Whenever the interpreter is in a stable configuration, it makes an attempt to dequeue an external event, which will cause this callback to be triggered. If we return an event, it will be processed by triggering transitions and a change in the configuration, if we return <code>NULL</code>, the state-chart will <code>IDLE</code>.</li>
<li><code>isInState</code> is not formally a callback to be registered by the context but very useful to dispatch upon the configuration of the state chart later.</li>
</ul>
</li>
<li>In <code>setup</code>, we initialize the state of the platform after the <code>reset</code> button is pressed or the power came back on. I.e. we connect the callbacks and initialize the state chart by proceeding to the first <code>IDLE</code> interpreter state.</li>
<li>In <code>loop</code> we process one cycle of the controller. We turn the LED on to indicate that we are processing and read the capacitive sensors if the invoker is active. Then we read the amount of light that arrives at the solar module via the voltage divider connected to <code>LIGHT</code> and transition accordingly. Afterwards we check if it is time to send the eventual <code>idle</code> event to turn of the pumps or check if we ought to activate a pump.</li>
</ul>
<p>One thing that helped me when developing the scaffolding was to thing about the configuration the state chart would eventually be in and observe the various events it would react to. Then to make sure that these events would be delivered when they are relevant.</p>
<h1><a class="anchor" id="resources"></a>
Resources</h1>
<p>The resources required when deploying this program on the ATMega328 are given as follows: </p><pre class="fragment">Program:   10534 bytes (32.1% Full)
(.text + .data + .bootloader)

Data:       1636 bytes (79.9% Full)
(.data + .bss + .noinit)
</pre><p>There are still quite some possibilities to reduce these resources some more if we are pressed on space:</p>
<ul>
<li>Event and invoker names can be enumerated</li>
<li>We can drop some unused callbacks from the <code>uscxm_ctx</code> struct</li>
<li>We can remove most fields of the <code><a class="el" href="structuscxml__elem__send.html" title="All information pertaining to a <send> element. ">uscxml_elem_send</a></code> struct </li>
</ul>
</div></div><!-- contents -->
<!-- HTML footer for doxygen 1.8.8-->
<!-- start footer part -->
</div>
</div>
</div>
</div>
</div>
<!-- <hr class="footer"/><address class="footer"><small>
Generated on Sun Apr 30 2017 22:52:20 for uSCXML by &#160;<a href="http://www.doxygen.org/index.html">
<img class="footer" src="doxygen.png" alt="doxygen"/>
</a> 1.8.10
</small></address> -->
</body>
</html>