Skip to content

Commit 6338e94

Browse files
committed
added experiments 4 - 11
1 parent 9d0e4f7 commit 6338e94

35 files changed

+4466
-0
lines changed
Lines changed: 356 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,356 @@
1+
/*
2+
EMBRYO Control system v2.0
3+
4+
Machine control using an event driven approach and designing
5+
a state machine around the different inputs and outputs
6+
7+
Test 04: Machine Basic Operations
8+
This example runs a simple state machine looking at the
9+
functionality of some of the inputs and prints out the
10+
current mode of operation
11+
12+
Notes: revised names for END_STOPs, now there are called
13+
PIN_END_STOP_TOP, and PIN_END_STOP_BOTTOM, making it
14+
easier to follow the code. Moved printInputs to
15+
serialPrintInputs
16+
17+
The state machine responds to the following diagram:
18+
19+
+---------+
20+
| |
21+
+------> RESET |
22+
| | | +------------+
23+
| +----+----+ AUTO | |
24+
| | +-----------------+ END LOOP |
25+
| | | | |
26+
| -INIT- | | +------^-----+
27+
| BUTTON | | |
28+
| | | | END STOP
29+
| | | | SWITCHES
30+
| | | |
31+
| +----v--v-+ +------+------+
32+
| | | L+R BUTTONS | |
33+
| | INIT +---------------> OPERATION |
34+
| | | | |
35+
| +---------+ +------+------+
36+
| |
37+
+---+---------+ |
38+
|+-----------+| |
39+
|| EMERGENCY || |
40+
|| STOP || EMERGENCY STOP BUTTON |
41+
|| |<-----------------------------+
42+
|+-----------+|
43+
+-------------+
44+
45+
This code is in the public domain
46+
47+
2021 D. Cuartielles
48+
49+
*/
50+
51+
// Include the machine's architecture
52+
#include "architecture.h"
53+
#include "states.h"
54+
55+
// Include the sensor / actuator handling library
56+
#include <EduIntro.h>
57+
58+
// Shall we debug the code?
59+
const int DEBUG = true;
60+
61+
// Array to store input values
62+
int inputValuesOld[NUM_PINS_DIGITAL + NUM_PINS_ANALOG];
63+
int inputValues[NUM_PINS_DIGITAL + NUM_PINS_ANALOG];
64+
65+
// Array to store the output values
66+
int outputValues[NUM_PINS_OUTPUT];
67+
68+
// Array for all of the buttons
69+
// unfortunately this cannot be declared automatically
70+
// like with
71+
// for (int i = 0; i < NUM_PINS_DIGITAL; i++)
72+
// inputButtons[i] = new Button(INPUTS_DIGITAL[i]);
73+
// and therefore cannot be automated :-(
74+
Button inputButtons[] {
75+
Button(INPUTS_DIGITAL[0], PULL_DOWN),
76+
Button(INPUTS_DIGITAL[1], PULL_DOWN),
77+
Button(INPUTS_DIGITAL[2], PULL_DOWN),
78+
Button(INPUTS_DIGITAL[3], PULL_DOWN),
79+
Button(INPUTS_DIGITAL[4], PULL_DOWN),
80+
Button(INPUTS_DIGITAL[5], PULL_DOWN),
81+
Button(INPUTS_DIGITAL[6], PULL_DOWN),
82+
Button(INPUTS_DIGITAL[7], PULL_UP),
83+
};
84+
85+
// State machine variables
86+
int currentState = RESET;
87+
int currentOperationState = STOP;
88+
int currentOperationMode = MANUAL;
89+
90+
// used in automatic mode to detect whether the cycle is done
91+
// 1 - done
92+
// 0 - not done
93+
// -1 - forced init cycle (in the unlikely case the machine stopped half way)
94+
int firstCycle = 1;
95+
96+
// Machine movement variables
97+
long speed = 0; // XXX not used
98+
99+
void setup() {
100+
// Initialise serial communication
101+
Serial.begin(115200);
102+
103+
// Do not start until computer is connected
104+
while (!Serial) {};
105+
106+
// Status prints
107+
if (DEBUG) {
108+
serialSystemVars();
109+
}
110+
111+
// Declare outputs as such
112+
for (int i = 0; i < NUM_PINS_OUTPUT; i++)
113+
pinMode(OUTPUTS[i], OUTPUT);
114+
}
115+
116+
void loop() {
117+
// Check the inputs
118+
readInputs();
119+
120+
// Serial terminal
121+
serialCheck();
122+
123+
// There is an event, process the state machine
124+
if (inputEvent()) {
125+
// Print out the inputs if there is an event
126+
if (DEBUG) serialPrintInputs();
127+
128+
// for the handling of inputs, remember that the
129+
// array of inputValues goes as follows:
130+
// 0 1 2 3 4 5 6 7 8
131+
// {LEFT, RIGHT, UP, DOWN, BOTTOM, TOP, INIT, EMERGENCY, AUTO/MANUAL}
132+
133+
switch ( currentState ) {
134+
case RESET:
135+
// if the init button is pressed enter init state
136+
if (inputValues[6] == PRESSED) currentState = INIT;
137+
break;
138+
case INIT:
139+
// set operation mode
140+
currentOperationMode = inputValues[8];
141+
142+
// in this state the system waits until L + R are HELD to
143+
// continue to the OPERATION state
144+
if (inputValues[0] == HELD && inputValues[1] == HELD) {
145+
firstCycle = -1; // configure a possible AUTOMATIC cycle reboot
146+
currentOperationState = STOP;
147+
currentState = OPERATION;
148+
}
149+
break;
150+
case OPERATION:
151+
// jump to the operation sub-state machine
152+
processOperation();
153+
break;
154+
case END_LOOP:
155+
break;
156+
case EMERGENCY_STOP:
157+
break;
158+
default:
159+
break;
160+
}
161+
}
162+
163+
// Copy arrays of inputs to check state changes
164+
copyInputs();
165+
}
166+
167+
/* Process operation
168+
169+
First check whether we operate automatic or manual mode, distinguish
170+
between two different sub-state-machines for the operation state:
171+
automatic or manual (see diagrams in the code)
172+
173+
For the handling of inputs, remember that the
174+
array of inputValues goes as follows:
175+
0 1 2 3 4 5 6 7 8
176+
{LEFT, RIGHT, UP, DOWN, BOTTOM, TOP, INIT, EMERGENCY, AUTO/MANUAL}
177+
*/
178+
void processOperation() {
179+
if (currentOperationMode == AUTOMATIC) {
180+
processAutomaticOperation();
181+
} else {
182+
processManualOperation();
183+
}
184+
}
185+
186+
void processAutomaticOperation() {
187+
/** AUTOMATIC MODE OF OPERATION **
188+
189+
+-----+
190+
| |!ENDSTOP
191+
+------------+ L + R +---------+--+ | BOTTOM
192+
| +------------> |<-+
193+
| STOP | | A_DOWN |
194+
| <------------+ |
195+
+------^-----+ !L + !R +---------+--+
196+
| |
197+
| |ENDSTOP
198+
| |BOTTOM
199+
| |
200+
| +---------v--+
201+
| | |
202+
+------------------+ A_UP |
203+
!L + !R + | |<-+
204+
ENDSTOP TOP +---------+--+ |!ENDSTOP
205+
| | TOP
206+
+-----+
207+
208+
*/
209+
210+
switch (currentOperationState) {
211+
case STOP:
212+
// will operate only if there have been no automatic cycles
213+
// done, otherwise, the user will have to release the buttons
214+
if (firstCycle != 0) {
215+
// Move down if LEFT, RIGHT and TOP are HELD
216+
if (inputValues[0] == HELD && inputValues[1] == HELD &&
217+
inputValues[5] == HELD) {
218+
currentOperationState = AUTO_DOWN;
219+
}
220+
// Move up if LEFT, and RIGHT are HELD and TOP and BOTTOM are RELEASED
221+
if (inputValues[0] == HELD && inputValues[1] == HELD &&
222+
inputValues[4] == RELEASED && inputValues[5] == RELEASED) {
223+
currentOperationState = AUTO_UP;
224+
firstCycle = -1; // mark this as a configuration cycle
225+
}
226+
}
227+
break;
228+
case AUTO_UP:
229+
// move up for as long as LEFT, and RIGHT are HELD and TOP is not pressed
230+
if (inputValues[0] == HELD && inputValues[1] == HELD &&
231+
inputValues[5] == RELEASED) {
232+
if (DEBUG) Serial.println(F("** MOVING UP **"));
233+
} else {
234+
currentOperationState = STOP;
235+
if (DEBUG) Serial.println(F("** STOP **"));
236+
if (inputValues[5] == PRESSED || inputValues[5] == HELD) {
237+
if (DEBUG) Serial.println(F("** REASON: reached top **"));
238+
239+
// if it was a config cycle then consider it the first cycle
240+
// otherwise consider the job done
241+
if (firstCycle == -1) {
242+
firstCycle = 1;
243+
} else {
244+
firstCycle = 0;
245+
}
246+
} else {
247+
if (DEBUG) Serial.println(F("** REASON: buttons released **"));
248+
249+
// here we should leave the operation mode and go back to init mode
250+
currentState = INIT;
251+
}
252+
}
253+
break;
254+
case AUTO_DOWN:
255+
// move down for as long as LEFT, and RIGHT are HELD and BOTTOM is not pressed
256+
if (inputValues[0] == HELD && inputValues[1] == HELD &&
257+
inputValues[4] == RELEASED) {
258+
if (DEBUG) Serial.println(F("** MOVING DOWN **"));
259+
} else {
260+
currentOperationState = AUTO_UP;
261+
if (DEBUG) Serial.println(F("** STOP - and UP**"));
262+
if (inputValues[4] == PRESSED || inputValues[4] == HELD) {
263+
if (DEBUG) Serial.println(F("** REASON: reached bottom **"));
264+
} else {
265+
if (DEBUG) Serial.println(F("** REASON: buttons released **"));
266+
267+
// here we should leave the operation mode and go back to init mode
268+
currentState = INIT;
269+
}
270+
}
271+
break;
272+
}
273+
}
274+
275+
void processManualOperation() {
276+
/** MANUAL MODE OF OPERATION **
277+
278+
279+
+------------+ L + R + UP +------------+
280+
| +----------------> |
281+
| STOP | | M_UP |
282+
| <----------------+ |<-+
283+
+--^------+--+ !L + !R + +---------+--+ |!ENDSTOP
284+
| | !UP + | | TOP
285+
| | ENDSTOP TOP +-----+
286+
!L + !R +| |
287+
!DOWN + | |
288+
ENDSTOP | |L + R +
289+
BOTTOM | |DOWN
290+
| |
291+
| |
292+
+--+------v--+
293+
| |
294+
| M_DOWN |
295+
| |<-+
296+
+---------+--+ |!ENDSTOP
297+
| | BOTTOM
298+
+-----+
299+
300+
*/
301+
302+
switch (currentOperationState) {
303+
case STOP:
304+
// Move up if L + R + UP are HELD and TOP is RELEASED
305+
if (inputValues[0] == HELD && inputValues[1] == HELD &&
306+
inputValues[2] == HELD && inputValues[5] == RELEASED) {
307+
currentOperationMode = MAN_UP;
308+
}
309+
// Move down if L + R + DOWN are HELD and BOTTOM is RELEASED
310+
if (inputValues[0] == HELD && inputValues[1] == HELD &&
311+
inputValues[3] == HELD && inputValues[4] == RELEASED) {
312+
currentOperationMode = MAN_DOWN;
313+
}
314+
break;
315+
case MAN_UP:
316+
// move up for as long as LEFT, RIGHT, and UP are HELD and TOP is not pressed
317+
if (inputValues[0] == HELD && inputValues[1] == HELD &&
318+
inputValues[2] == HELD && inputValues[5] == RELEASED) {
319+
if (DEBUG) Serial.println(F("** MOVING UP **"));
320+
} else {
321+
currentOperationMode = STOP;
322+
if (DEBUG) Serial.println(F("** STOP **"));
323+
if (inputValues[5] == PRESSED || inputValues[5] == HELD) {
324+
if (DEBUG) Serial.println(F("** REASON: reached top **"));
325+
} else {
326+
if (DEBUG) Serial.println(F("** REASON: buttons released **"));
327+
328+
if (inputValues[0] == RELEASED || inputValues[1] == RELEASED) {
329+
// here we should leave the operation mode and go back to init mode
330+
currentState = INIT;
331+
}
332+
}
333+
}
334+
break;
335+
case MAN_DOWN:
336+
// move down for as long as LEFT, RIGHT, and DOWN are HELD and BOTTOM is not pressed
337+
if (inputValues[0] == HELD && inputValues[1] == HELD &&
338+
inputValues[3] == HELD && inputValues[4] == RELEASED) {
339+
if (DEBUG) Serial.println(F("** MOVING DOWN **"));
340+
} else {
341+
currentOperationMode = STOP;
342+
if (DEBUG) Serial.println(F("** STOP **"));
343+
if (inputValues[5] == PRESSED || inputValues[4] == HELD) {
344+
if (DEBUG) Serial.println(F("** REASON: reached bottom **"));
345+
} else {
346+
if (DEBUG) Serial.println(F("** REASON: buttons released **"));
347+
348+
if (inputValues[0] == RELEASED || inputValues[1] == RELEASED) {
349+
// here we should leave the operation mode and go back to init mode
350+
currentState = INIT;
351+
}
352+
}
353+
}
354+
break;
355+
}
356+
}

0 commit comments

Comments
 (0)