├── .gitignore ├── images ├── example │ ├── Blink.png │ ├── Debounce.png │ ├── Analog-High-Alarm.png │ ├── Coin-Operated-Turnstile.png │ ├── Traffic-Light-Diagram.png │ ├── Fan-Control-With-A-Thermostat-Diagram.png │ ├── Fan-Control-With-A-Thermostat.svg │ ├── Coin-Operated-Turnstile.svg │ ├── Blink.svg │ └── Coin-Operated-Turnstile-With-Event.svg ├── wokwi-sim │ └── wokwi-simulate-black.svg ├── Transition-Member.svg └── timer-type │ ├── not-used-timer │ ├── option2-predicate-with-process.svg │ ├── option3-predicate-with-event.svg │ ├── option1-predicate-with-process-and-event.svg │ └── not-used-timer-state-diagram.svg │ ├── transition-timer │ ├── option2-transition-timer-with-process.svg │ ├── option3-transition-timer-with-event.svg │ └── option1-transition-timer-with-process-and-event.svg │ └── true-timer │ └── option2-true-timer-with-process.svg ├── examples ├── AuCP_Blink │ ├── diagram.json │ └── AuCP_Blink.ino ├── AuCP_Debounce │ ├── diagram.json │ └── AuCP_Debounce.ino ├── AuCP_Fan-Control-With-A-Thermostat │ ├── diagram.json │ └── AuCP_Fan-Control-With-A-Thermostat.ino ├── AuCP_Traffic-Light │ ├── diagram.json │ └── AuCP_Traffic-Light.ino ├── AuCP_Traffic-Light-With-Transition-Timer │ ├── diagram.json │ └── AuCP_Traffic-Light-With-Transition-Timer.ino ├── AuCP_Coin-Operated-Turnstile │ ├── diagram.json │ └── AuCP_Coin-Operated-Turnstile.ino ├── AuCP_Coin-Operated-Turnstile-With-Event │ ├── diagram.json │ └── AuCP_Coin-Operated-Turnstile-With-Event.ino └── AuCP_Analog-High-Alarm │ ├── diagram.json │ └── AuCP_Analog-High-Alarm.ino ├── library.properties ├── .github └── workflows │ └── main.yml ├── LICENSE ├── keywords.txt └── src ├── FiniteState.h └── FiniteState.cpp /.gitignore: -------------------------------------------------------------------------------- 1 | # VSCode 2 | .vscode -------------------------------------------------------------------------------- /images/example/Blink.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MicroBeaut/Finite-State/HEAD/images/example/Blink.png -------------------------------------------------------------------------------- /images/example/Debounce.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MicroBeaut/Finite-State/HEAD/images/example/Debounce.png -------------------------------------------------------------------------------- /images/example/Analog-High-Alarm.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MicroBeaut/Finite-State/HEAD/images/example/Analog-High-Alarm.png -------------------------------------------------------------------------------- /images/example/Coin-Operated-Turnstile.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MicroBeaut/Finite-State/HEAD/images/example/Coin-Operated-Turnstile.png -------------------------------------------------------------------------------- /images/example/Traffic-Light-Diagram.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MicroBeaut/Finite-State/HEAD/images/example/Traffic-Light-Diagram.png -------------------------------------------------------------------------------- /images/example/Fan-Control-With-A-Thermostat-Diagram.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MicroBeaut/Finite-State/HEAD/images/example/Fan-Control-With-A-Thermostat-Diagram.png -------------------------------------------------------------------------------- /examples/AuCP_Blink/diagram.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": 1, 3 | "author": "MicroBeaut", 4 | "editor": "wokwi", 5 | "parts": [ 6 | { 7 | "type": "wokwi-arduino-uno", 8 | "id": "uno", 9 | "top": -9.59, 10 | "left": -58.88, 11 | "rotate": 90, 12 | "attrs": {} 13 | } 14 | ], 15 | "connections": [], 16 | "dependencies": {} 17 | } -------------------------------------------------------------------------------- /library.properties: -------------------------------------------------------------------------------- 1 | name=Finite-State 2 | version=1.6.0 3 | author=Montree Hamarn, Natvalun Tavepontakul 4 | maintainer=Montree Hamarn 5 | sentence=Finite-State Machine (FSM) for Arduino. 6 | paragraph=Finite-State provides a bounded state machine that combines state transitions, including predicate, process, event state callback functions, and timer. 7 | category=Other 8 | url=https://github.com/MicroBeaut/Finite-State 9 | architectures=* -------------------------------------------------------------------------------- /.github/workflows/main.yml: -------------------------------------------------------------------------------- 1 | name: ArduinoLintAction 2 | 3 | # Controls when the workflow will run 4 | on: 5 | # Triggers the workflow on push or pull request events but only for the "main" branch 6 | push: 7 | branches: [ "main" ] 8 | pull_request: 9 | branches: [ "main" ] 10 | 11 | # Allows you to run this workflow manually from the Actions tab 12 | workflow_dispatch: 13 | 14 | # A workflow run is made up of one or more jobs that can run sequentially or in parallel 15 | jobs: 16 | # This workflow contains a single job called "build" 17 | build: 18 | # The type of runner that the job will run on 19 | runs-on: ubuntu-latest 20 | 21 | # Steps represent a sequence of tasks that will be executed as part of the job 22 | steps: 23 | # Checks-out your repository under $GITHUB_WORKSPACE, so your job can access it 24 | - uses: actions/checkout@v3 25 | 26 | # Arduino Lint 27 | - uses: arduino/arduino-lint-action@v1 28 | with: 29 | library-manager: update 30 | compliance: strict -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2023 MicroBeaut 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. -------------------------------------------------------------------------------- /examples/AuCP_Debounce/diagram.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": 1, 3 | "author": "MicroBeaut", 4 | "editor": "wokwi", 5 | "parts": [ 6 | { 7 | "type": "wokwi-arduino-uno", 8 | "id": "uno", 9 | "top": -9.59, 10 | "left": -58.88, 11 | "rotate": 90, 12 | "attrs": {} 13 | }, 14 | { 15 | "type": "wokwi-pushbutton", 16 | "id": "btn1", 17 | "top": 132.81, 18 | "left": -110, 19 | "attrs": { "color": "DARKRED", "label": "BUTTON", "bounce": "1" } 20 | }, 21 | { 22 | "type": "wokwi-led", 23 | "id": "led1", 24 | "top": 5, 25 | "left": 200, 26 | "attrs": { "color": "red", "label": "LED" } 27 | }, 28 | { 29 | "type": "wokwi-resistor", 30 | "id": "r9", 31 | "top": 100, 32 | "left": 195, 33 | "rotate": 90, 34 | "attrs": { "value": "220" } 35 | } 36 | ], 37 | "connections": [ 38 | [ "r9:1", "led1:A", "green", [ "h0" ] ], 39 | [ "uno:GND.1", "led1:C", "black", [ "h0" ] ], 40 | [ "uno:7", "r9:2", "green", [ "h0" ] ], 41 | [ "uno:A0", "btn1:2.r", "green", [ "h0" ] ], 42 | [ "uno:GND.2", "btn1:1.l", "black", [ "h-119.84", "v88.05" ] ] 43 | ], 44 | "dependencies": {} 45 | } -------------------------------------------------------------------------------- /keywords.txt: -------------------------------------------------------------------------------- 1 | ####################################### 2 | # Syntax Coloring Map For Finite-State 3 | ####################################### 4 | 5 | ####################################### 6 | # Datatypes (KEYWORD1) 7 | ####################################### 8 | FiniteState KEYWORD1 9 | Action KEYWORD1 10 | TimerType KEYWORD1 11 | TriState KEYWORD1 12 | EventArgs KEYWORD1 13 | Transition KEYWORD1 14 | id_t KEYWORD1 15 | time_t KEYWORD1 16 | 17 | ####################################### 18 | # Methods and Functions (KEYWORD2) 19 | ####################################### 20 | Predicate KEYWORD2 21 | Process KEYWORD2 22 | EventHandler KEYWORD2 23 | begin KEYWORD2 24 | transition KEYWORD2 25 | execute KEYWORD2 26 | id KEYWORD2 27 | size KEYWORD2 28 | 29 | ####################################### 30 | # Constants (LITERAL1) 31 | ####################################### 32 | FINITE_STATE_VERSION LITERAL1 33 | FINITE_STATE_AUTHOR LITERAL1 34 | STATE_TRANSITION_MIN LITERAL1 35 | STATE_TRANSITION_MAX LITERAL1 36 | NONE LITERAL1 37 | EXIT LITERAL1 38 | ENTRY LITERAL1 39 | NOT_USED LITERAL1 40 | TRANS_TIMER LITERAL1 41 | PREDIC_TIMER LITERAL1 42 | FALSE_TIMER LITERAL1 43 | TRUE_TIMER LITERAL1 44 | Unspecified LITERAL1 45 | False LITERAL1 46 | True LITERAL1 -------------------------------------------------------------------------------- /examples/AuCP_Fan-Control-With-A-Thermostat/diagram.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": 1, 3 | "author": "MicroBeaut", 4 | "editor": "wokwi", 5 | "parts": [ 6 | { 7 | "type": "wokwi-arduino-uno", 8 | "id": "uno", 9 | "top": -9.59, 10 | "left": -58.88, 11 | "rotate": 90, 12 | "attrs": {} 13 | }, 14 | { 15 | "type": "wokwi-led", 16 | "id": "led1", 17 | "top": 5, 18 | "left": 202, 19 | "attrs": { "color": "red", "label": "ST" } 20 | }, 21 | { 22 | "type": "wokwi-led", 23 | "id": "led2", 24 | "top": 5, 25 | "left": 245, 26 | "attrs": { "color": "green", "label": "SP" } 27 | }, 28 | { 29 | "type": "wokwi-resistor", 30 | "id": "r8", 31 | "top": 100, 32 | "left": 241, 33 | "rotate": 90, 34 | "attrs": { "value": "220" } 35 | }, 36 | { 37 | "type": "wokwi-resistor", 38 | "id": "r9", 39 | "top": 100, 40 | "left": 198, 41 | "rotate": 90, 42 | "attrs": { "value": "220" } 43 | }, 44 | { 45 | "type": "wokwi-slide-potentiometer", 46 | "id": "pot1", 47 | "top": 29.34, 48 | "left": -220, 49 | "rotate": 270, 50 | "attrs": { "travelLength": "50" } 51 | } 52 | ], 53 | "connections": [ 54 | [ "uno:5", "r8:2", "green", [ "h0" ] ], 55 | [ "uno:6", "r9:2", "green", [ "h0" ] ], 56 | [ "r9:1", "led1:A", "green", [ "h0" ] ], 57 | [ "r8:1", "led2:A", "green", [ "h0" ] ], 58 | [ "uno:GND.1", "led1:C", "black", [ "h0" ] ], 59 | [ "uno:GND.3", "uno:GND.2", "black", [ "h0" ] ], 60 | [ "uno:GND.2", "pot1:GND", "black", [ "h-32.64", "v-201.63", "h-50.59" ] ], 61 | [ "uno:5V", "pot1:VCC", "red", [ "h-22.17", "v-200.85", "h-91.59", "v324.49", "h46.23" ] ], 62 | [ "uno:A0", "pot1:SIG", "green", [ "h-22.17", "v75.64", "h-109.04" ] ], 63 | [ "uno:GND.1", "led2:C", "black", [ "h0" ] ] 64 | ], 65 | "dependencies": {} 66 | } -------------------------------------------------------------------------------- /examples/AuCP_Traffic-Light/diagram.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": 1, 3 | "author": "MicroBeaut", 4 | "editor": "wokwi", 5 | "parts": [ 6 | { 7 | "type": "wokwi-arduino-uno", 8 | "id": "uno", 9 | "top": -9.59, 10 | "left": -58.88, 11 | "rotate": 90, 12 | "attrs": {} 13 | }, 14 | { 15 | "type": "wokwi-led", 16 | "id": "led1", 17 | "top": 5, 18 | "left": 202.45, 19 | "attrs": { "color": "red", "label": "R" } 20 | }, 21 | { 22 | "type": "wokwi-led", 23 | "id": "led2", 24 | "top": 5.81, 25 | "left": 244.26, 26 | "attrs": { "color": "yellow", "label": "Y" } 27 | }, 28 | { 29 | "type": "wokwi-led", 30 | "id": "led3", 31 | "top": 5, 32 | "left": 285.09, 33 | "attrs": { "color": "green", "label": "G" } 34 | }, 35 | { 36 | "type": "wokwi-resistor", 37 | "id": "r5", 38 | "top": 100, 39 | "left": 280.08, 40 | "rotate": 90, 41 | "attrs": { "value": "220" } 42 | }, 43 | { 44 | "type": "wokwi-resistor", 45 | "id": "r8", 46 | "top": 100, 47 | "left": 237.94, 48 | "rotate": 90, 49 | "attrs": { "value": "220" } 50 | }, 51 | { 52 | "type": "wokwi-resistor", 53 | "id": "r9", 54 | "top": 96.58, 55 | "left": 195.81, 56 | "rotate": 90, 57 | "attrs": { "value": "220" } 58 | } 59 | ], 60 | "connections": [ 61 | [ "r9:1", "led1:A", "green", [ "h0" ] ], 62 | [ "r8:1", "led2:A", "green", [ "h0" ] ], 63 | [ "uno:GND.1", "led1:C", "black", [ "h0" ] ], 64 | [ "uno:GND.1", "led2:C", "black", [ "h0" ] ], 65 | [ "r5:1", "led3:A", "green", [ "h0" ] ], 66 | [ "uno:GND.1", "led3:C", "black", [ "h0" ] ], 67 | [ "uno:GND.1", "led6:C", "black", [ "h0" ] ], 68 | [ "uno:GND.1", "led7:C", "black", [ "h0" ] ], 69 | [ "uno:3", "r5:2", "green", [ "h0" ] ], 70 | [ "uno:4", "r8:2", "green", [ "h0" ] ], 71 | [ "uno:5", "r9:2", "green", [ "h0" ] ] 72 | ], 73 | "dependencies": {} 74 | } -------------------------------------------------------------------------------- /examples/AuCP_Traffic-Light-With-Transition-Timer/diagram.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": 1, 3 | "author": "MicroBeaut", 4 | "editor": "wokwi", 5 | "parts": [ 6 | { 7 | "type": "wokwi-arduino-uno", 8 | "id": "uno", 9 | "top": -9.59, 10 | "left": -58.88, 11 | "rotate": 90, 12 | "attrs": {} 13 | }, 14 | { 15 | "type": "wokwi-led", 16 | "id": "led1", 17 | "top": 5, 18 | "left": 202.45, 19 | "attrs": { "color": "red", "label": "R" } 20 | }, 21 | { 22 | "type": "wokwi-led", 23 | "id": "led2", 24 | "top": 5.81, 25 | "left": 244.26, 26 | "attrs": { "color": "yellow", "label": "Y" } 27 | }, 28 | { 29 | "type": "wokwi-led", 30 | "id": "led3", 31 | "top": 5, 32 | "left": 285.09, 33 | "attrs": { "color": "green", "label": "G" } 34 | }, 35 | { 36 | "type": "wokwi-resistor", 37 | "id": "r5", 38 | "top": 100, 39 | "left": 280.08, 40 | "rotate": 90, 41 | "attrs": { "value": "220" } 42 | }, 43 | { 44 | "type": "wokwi-resistor", 45 | "id": "r8", 46 | "top": 100, 47 | "left": 237.94, 48 | "rotate": 90, 49 | "attrs": { "value": "220" } 50 | }, 51 | { 52 | "type": "wokwi-resistor", 53 | "id": "r9", 54 | "top": 96.58, 55 | "left": 195.81, 56 | "rotate": 90, 57 | "attrs": { "value": "220" } 58 | } 59 | ], 60 | "connections": [ 61 | [ "r9:1", "led1:A", "green", [ "h0" ] ], 62 | [ "r8:1", "led2:A", "green", [ "h0" ] ], 63 | [ "uno:GND.1", "led1:C", "black", [ "h0" ] ], 64 | [ "uno:GND.1", "led2:C", "black", [ "h0" ] ], 65 | [ "r5:1", "led3:A", "green", [ "h0" ] ], 66 | [ "uno:GND.1", "led3:C", "black", [ "h0" ] ], 67 | [ "uno:GND.1", "led6:C", "black", [ "h0" ] ], 68 | [ "uno:GND.1", "led7:C", "black", [ "h0" ] ], 69 | [ "uno:3", "r5:2", "green", [ "h0" ] ], 70 | [ "uno:4", "r8:2", "green", [ "h0" ] ], 71 | [ "uno:5", "r9:2", "green", [ "h0" ] ] 72 | ], 73 | "dependencies": {} 74 | } -------------------------------------------------------------------------------- /examples/AuCP_Coin-Operated-Turnstile/diagram.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": 1, 3 | "author": "MicroBeaut", 4 | "editor": "wokwi", 5 | "parts": [ 6 | { 7 | "type": "wokwi-arduino-uno", 8 | "id": "uno", 9 | "top": -9.59, 10 | "left": -58.88, 11 | "rotate": 90, 12 | "attrs": {} 13 | }, 14 | { 15 | "type": "wokwi-pushbutton", 16 | "id": "btn1", 17 | "top": 133.48, 18 | "left": -110, 19 | "attrs": { "color": "DARKRED", "label": "Coin", "bounce": "1" } 20 | }, 21 | { 22 | "type": "wokwi-pushbutton", 23 | "id": "btn2", 24 | "top": 195.48, 25 | "left": -110, 26 | "attrs": { "color": "DARKBLUE", "label": "Arm", "bounce": "1" } 27 | }, 28 | { 29 | "type": "wokwi-led", 30 | "id": "led1", 31 | "top": 5, 32 | "left": 200, 33 | "attrs": { "color": "red", "label": "Locked" } 34 | }, 35 | { 36 | "type": "wokwi-led", 37 | "id": "led2", 38 | "top": 5, 39 | "left": 240, 40 | "attrs": { "color": "blue", "label": "Unlocked" } 41 | }, 42 | { 43 | "type": "wokwi-resistor", 44 | "id": "r8", 45 | "top": 100, 46 | "left": 235, 47 | "rotate": 90, 48 | "attrs": { "value": "220" } 49 | }, 50 | { 51 | "type": "wokwi-resistor", 52 | "id": "r9", 53 | "top": 100, 54 | "left": 195, 55 | "rotate": 90, 56 | "attrs": { "value": "220" } 57 | } 58 | ], 59 | "connections": [ 60 | [ "uno:A1", "btn2:2.r", "green", [ "h-21.7", "v52.89" ] ], 61 | [ "r9:1", "led1:A", "green", [ "h0" ] ], 62 | [ "r8:1", "led2:A", "green", [ "h0" ] ], 63 | [ "uno:GND.1", "led1:C", "black", [ "h0" ] ], 64 | [ "uno:GND.1", "led2:C", "black", [ "h0" ] ], 65 | [ "uno:7", "r9:2", "green", [ "h0" ] ], 66 | [ "uno:6", "r8:2", "green", [ "h0" ] ], 67 | [ "uno:A0", "btn1:2.r", "green", [ "h0" ] ], 68 | [ "uno:GND.2", "btn2:1.l", "black", [ "h-119.84", "v83.56" ] ], 69 | [ "uno:GND.2", "btn1:1.l", "black", [ "h-119.84", "v88.05" ] ] 70 | ], 71 | "dependencies": {} 72 | } -------------------------------------------------------------------------------- /examples/AuCP_Coin-Operated-Turnstile-With-Event/diagram.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": 1, 3 | "author": "MicroBeaut", 4 | "editor": "wokwi", 5 | "parts": [ 6 | { 7 | "type": "wokwi-arduino-uno", 8 | "id": "uno", 9 | "top": -9.59, 10 | "left": -58.88, 11 | "rotate": 90, 12 | "attrs": {} 13 | }, 14 | { 15 | "type": "wokwi-pushbutton", 16 | "id": "btn1", 17 | "top": 133.48, 18 | "left": -110, 19 | "attrs": { "color": "DARKRED", "label": "Coin", "bounce": "1" } 20 | }, 21 | { 22 | "type": "wokwi-pushbutton", 23 | "id": "btn2", 24 | "top": 195.48, 25 | "left": -110, 26 | "attrs": { "color": "DARKBLUE", "label": "Arm", "bounce": "1" } 27 | }, 28 | { 29 | "type": "wokwi-led", 30 | "id": "led1", 31 | "top": 5, 32 | "left": 200, 33 | "attrs": { "color": "red", "label": "Locked" } 34 | }, 35 | { 36 | "type": "wokwi-led", 37 | "id": "led2", 38 | "top": 5, 39 | "left": 240, 40 | "attrs": { "color": "blue", "label": "Unlocked" } 41 | }, 42 | { 43 | "type": "wokwi-resistor", 44 | "id": "r8", 45 | "top": 100, 46 | "left": 235, 47 | "rotate": 90, 48 | "attrs": { "value": "220" } 49 | }, 50 | { 51 | "type": "wokwi-resistor", 52 | "id": "r9", 53 | "top": 100, 54 | "left": 195, 55 | "rotate": 90, 56 | "attrs": { "value": "220" } 57 | } 58 | ], 59 | "connections": [ 60 | [ "uno:A1", "btn2:2.r", "green", [ "h-21.7", "v52.89" ] ], 61 | [ "r9:1", "led1:A", "green", [ "h0" ] ], 62 | [ "r8:1", "led2:A", "green", [ "h0" ] ], 63 | [ "uno:GND.1", "led1:C", "black", [ "h0" ] ], 64 | [ "uno:GND.1", "led2:C", "black", [ "h0" ] ], 65 | [ "uno:7", "r9:2", "green", [ "h0" ] ], 66 | [ "uno:6", "r8:2", "green", [ "h0" ] ], 67 | [ "uno:A0", "btn1:2.r", "green", [ "h0" ] ], 68 | [ "uno:GND.2", "btn2:1.l", "black", [ "h-119.84", "v83.56" ] ], 69 | [ "uno:GND.2", "btn1:1.l", "black", [ "h-119.84", "v88.05" ] ] 70 | ], 71 | "dependencies": {} 72 | } -------------------------------------------------------------------------------- /examples/AuCP_Analog-High-Alarm/diagram.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": 1, 3 | "author": "MicroBeaut", 4 | "editor": "wokwi", 5 | "parts": [ 6 | { 7 | "type": "wokwi-arduino-uno", 8 | "id": "uno", 9 | "top": -9.59, 10 | "left": -58.88, 11 | "rotate": 90, 12 | "attrs": {} 13 | }, 14 | { 15 | "type": "wokwi-led", 16 | "id": "led1", 17 | "top": 5, 18 | "left": 200, 19 | "attrs": { "color": "green", "label": "Normal" } 20 | }, 21 | { 22 | "type": "wokwi-led", 23 | "id": "led2", 24 | "top": 5, 25 | "left": 245, 26 | "attrs": { "color": "yellow", "label": "Pre Alarm" } 27 | }, 28 | { 29 | "type": "wokwi-led", 30 | "id": "led3", 31 | "top": 5, 32 | "left": 290, 33 | "attrs": { "color": "red", "label": "High Alarm" } 34 | }, 35 | { 36 | "type": "wokwi-resistor", 37 | "id": "r1", 38 | "top": 100, 39 | "left": 240, 40 | "rotate": 90, 41 | "attrs": { "value": "220" } 42 | }, 43 | { 44 | "type": "wokwi-resistor", 45 | "id": "r2", 46 | "top": 100, 47 | "left": 195, 48 | "rotate": 90, 49 | "attrs": { "value": "220" } 50 | }, 51 | { 52 | "type": "wokwi-resistor", 53 | "id": "r3", 54 | "top": 100, 55 | "left": 285, 56 | "rotate": 90, 57 | "attrs": { "value": "220" } 58 | }, 59 | { 60 | "type": "wokwi-slide-potentiometer", 61 | "id": "pot1", 62 | "top": 29.34, 63 | "left": -228, 64 | "rotate": 270, 65 | "attrs": { "travelLength": "50" } 66 | } 67 | ], 68 | "connections": [ 69 | [ "uno:5", "r1:2", "green", [ "h0" ] ], 70 | [ "uno:6", "r2:2", "green", [ "h0" ] ], 71 | [ "r2:1", "led1:A", "green", [ "h0" ] ], 72 | [ "r1:1", "led2:A", "green", [ "h0" ] ], 73 | [ "uno:GND.1", "led1:C", "black", [ "h0" ] ], 74 | [ "uno:GND.3", "uno:GND.2", "black", [ "h0" ] ], 75 | [ "uno:GND.2", "pot1:GND", "black", [ "h-33.86", "v-198.04", "h-58.26" ] ], 76 | [ "uno:5V", "pot1:VCC", "red", [ "h-22.17", "v-200.85", "h-101.02", "v324.49", "h35.07" ] ], 77 | [ "uno:A0", "pot1:SIG", "green", [ "h-22.17", "v75.64", "h-109.04" ] ], 78 | [ "uno:GND.1", "led2:C", "black", [ "h0" ] ], 79 | [ "uno:GND.1", "led3:C", "black", [ "h0" ] ], 80 | [ "uno:4", "r3:2", "green", [ "h0" ] ], 81 | [ "led3:A", "r3:1", "green", [ "v0" ] ] 82 | ], 83 | "dependencies": {} 84 | } -------------------------------------------------------------------------------- /examples/AuCP_Blink/AuCP_Blink.ino: -------------------------------------------------------------------------------- 1 | /* 2 | AuCP_Blink.ino 3 | Created: 5-May-2023 4 | Author: MicroBeaut 5 | GitHub: https://github.com/MicroBeaut/Finite-State#blink 6 | */ 7 | 8 | #include "FiniteState.h" 9 | 10 | /* 11 | ____________________________________________________________________________________________________________________________________________________ 12 | | State-Transition Table | 13 | |___________________________________________________________________________________________________________________________________________________| 14 | | | | | Next-State | Next-State | | | Delay-Time | | 15 | | State | Id | Predicate | Fase | True | Process | Event | (milliseconds) | Timer-Type | 16 | |_____________|_______|___________________|_____________|_____________|_________________|_______________________|_________________|_________________| 17 | | LED_OFF | 0 | - | 0 | 1 | TurnOffProcess | - | 500 | TRANS_TIMER | 18 | | LED_ON | 1 | - | 1 | 0 | TrunOnProcess | - | 1,000 | TRANS_TIMER | 19 | |_____________|_______|___________________|_____________|_____________|_________________|_______________________|_________________|_________________| 20 | */ 21 | 22 | void TrunOnProcess(id_t id); // Declare Turn LED On Process function 23 | void TurnOffProcess(id_t id); // Declare Turn LED Off Process function 24 | 25 | enum LedState : id_t { 26 | LED_OFF, 27 | LED_ON 28 | }; 29 | 30 | Transition transitions[] = { 31 | {nullptr, LED_OFF, LED_ON, TurnOffProcess, nullptr, 500, TRANS_TIMER}, // State-0 - NextF = 0, NextT = 1 32 | {nullptr, LED_ON, LED_OFF, TrunOnProcess, nullptr, 1000, TRANS_TIMER} // State-1 - NextF = 1, NextT = 0 33 | }; 34 | const uint8_t numberOfTransitions = sizeof(transitions) / sizeof(Transition); // Calculate the number of transitions. 35 | 36 | FiniteState blinkFS(transitions, numberOfTransitions); // Finite-State Object 37 | 38 | void setup() { 39 | 40 | pinMode(LED_BUILTIN, OUTPUT); // Set the LED_BUILTIN pin mode 41 | blinkFS.begin(LED_OFF); // FSM begins with Initial Transition Id 0 42 | } 43 | 44 | void loop() { 45 | blinkFS.execute(); // Execute the FSM 46 | } 47 | 48 | void TrunOnProcess(id_t id) { 49 | digitalWrite(LED_BUILTIN, HIGH); // Turn on the LED. 50 | } 51 | 52 | void TurnOffProcess(id_t id) { 53 | digitalWrite(LED_BUILTIN, LOW); // Turn off the LED. 54 | } -------------------------------------------------------------------------------- /src/FiniteState.h: -------------------------------------------------------------------------------- 1 | /* 2 | FiniteState.h 3 | Created: 14-Apr-2023 4 | Author: MicroBeaut 5 | 6 | MIT License 7 | Copyright (c) 2023 MicroBeaut 8 | */ 9 | 10 | #ifndef FINITESTATE_H 11 | #define FINITESTATE_H 12 | 13 | #include "Arduino.h" 14 | 15 | #define FINITE_STATE_VERSION "1.6.0" 16 | #define FINITE_STATE_AUTHOR "MicroBeaut" 17 | 18 | #define STATE_TRANSITION_MIN 1 19 | #define STATE_TRANSITION_MAX 63 20 | 21 | #define id_t uint8_t 22 | #define time_t unsigned long 23 | 24 | enum Action { 25 | NONE, 26 | ENTRY, 27 | EXIT 28 | }; 29 | 30 | enum TimerType { 31 | NOT_USED, // Not Used Timer 32 | TRANS_TIMER, // Transition Timer 33 | PREDIC_TIMER, // Predicate Timer 34 | FALSE_TIMER, // False State Timer 35 | TRUE_TIMER, // True State Timer 36 | }; 37 | 38 | enum TriState { 39 | Unspecified = -1, 40 | False = 0, 41 | True = 1 42 | }; 43 | 44 | typedef struct { 45 | id_t id; // State id 46 | Action action; // Action State 47 | } EventArgs; 48 | 49 | typedef bool (*Predicate)(id_t); // Predicate Function Pointer 50 | typedef void (*Process)(id_t); // Process Function Pointer 51 | typedef void (*EventHandler)(EventArgs); // Event Handler Function Pointer 52 | 53 | typedef struct { 54 | Predicate predicate; // Predicate Function Pointer 55 | id_t nextF; // Next State on FALSE 56 | id_t nextT; // Next State on TRUE 57 | Process process; // Process Function Pointer 58 | EventHandler eventHandler; // Event Function Pointer 59 | time_t delayTime; // Delay Time 60 | TimerType timerType; // Timer Type 61 | } Transition; 62 | 63 | class FiniteState { 64 | private: 65 | Transition *_transitions; // Tranistion Pointer 66 | uint8_t _size; // Number of Transitions 67 | EventArgs _eventArgs; // Event Argument 68 | time_t _startTime; // Start Time 69 | bool _timeout; // Timeout State 70 | 71 | void InternalTimerCondition(); 72 | void InternalProcess(); 73 | 74 | void InternalNotUsedTimerCondition(); 75 | void InternalTransitionTimerCondition(); 76 | void InternalPredicateTimerCondition(); 77 | void InternalFalseStateTimerCondition(); 78 | void InternalTrueStateTimerCondition(); 79 | 80 | const TriState InternalPredicate(); 81 | 82 | void InternalNextState(TriState state); 83 | void InternalNextStateAction(const id_t id); 84 | 85 | void InternalEntryAction(const id_t id); 86 | void InternalExitAction(); 87 | 88 | void InternalEventHandler(const Action e); 89 | 90 | const TriState InternalTimer(); 91 | const bool InternalTimeout(); 92 | 93 | const bool InternalBadId(id_t id); 94 | const uint8_t InternalLimit(const uint8_t value, const uint8_t min, const uint8_t max); 95 | public: 96 | id_t &id; 97 | uint8_t &size; 98 | 99 | FiniteState(Transition *transitions, const uint8_t numberOfTransitions); 100 | void begin(const id_t id); 101 | void transition(const id_t id); 102 | void execute(); 103 | }; 104 | 105 | #endif // FINITESTATE_H -------------------------------------------------------------------------------- /examples/AuCP_Traffic-Light-With-Transition-Timer/AuCP_Traffic-Light-With-Transition-Timer.ino: -------------------------------------------------------------------------------- 1 | /* 2 | Sketch: AuCP_Traffic-Light-With-Transition-Timer.ino 3 | Created: 1-May-2023 4 | Author: MicroBeaut (μB) 5 | GitHub: https://github.com/MicroBeaut/Finite-State#traffic-light-with-transition-timer-trans_timer 6 | */ 7 | 8 | #include "FiniteState.h" 9 | 10 | #define redLightPin 5 11 | #define yellowLightPin 4 12 | #define greenLightPin 3 13 | 14 | uint8_t lightPins[] = {redLightPin, greenLightPin, yellowLightPin}; // Define an array of light pins. 15 | const uint8_t numberOfLights = sizeof(lightPins) / sizeof(uint8_t); // Calculate the number of lights. 16 | 17 | /* 18 | ____________________________________________________________________________________________________________________________________________________ 19 | | State-Transition Table | 20 | |___________________________________________________________________________________________________________________________________________________| 21 | | | | | Next-State | Next-State | | | Delay-Time | | 22 | | State | Id | Predicate | Fase | True | Process | Event | (milliseconds) | Timer-Type | 23 | |_____________|_______|___________________|_____________|_____________|_________________|_______________________|_________________|_________________| 24 | | RED | 0 | - | 0 | 1 | - | EventOnActionChanged | 5,000 | TRANS_TIMER | 25 | | GREEN | 1 | - | 1 | 2 | - | EventOnActionChanged | 10,000 | TRANS_TIMER | 26 | | YELLOW | 2 | - | 2 | 0 | - | EventOnActionChanged | 3,000 | TRANS_TIMER | 27 | |_____________|_______|___________________|_____________|_____________|_________________|_______________________|_________________|_________________| 28 | */ 29 | 30 | void EventOnActionChanged(EventArgs e); // Event State 31 | 32 | enum LightState : id_t { 33 | RED, 34 | GREEN, 35 | YELLOW 36 | }; 37 | 38 | Transition transitions[] = { 39 | {nullptr, RED, GREEN, nullptr, EventOnActionChanged, 5000, TRANS_TIMER}, // State-1 - NextF = 0, NextT = 1 40 | {nullptr, GREEN, YELLOW, nullptr, EventOnActionChanged, 10000, TRANS_TIMER}, // State-2 - NextF = 1, NextT = 2 41 | {nullptr, YELLOW, RED, nullptr, EventOnActionChanged, 3000, TRANS_TIMER}, // State-3 - NextF = 2, NextT = 0 42 | }; 43 | const uint8_t numberOfTransitions = sizeof(transitions) / sizeof(Transition); // Calculate the number of transitions. 44 | 45 | FiniteState finiteStateMachine(transitions, numberOfTransitions); // Define Finite-State Object 46 | 47 | void setup() { 48 | for (uint8_t index = 0; index < numberOfLights; index ++) { 49 | pinMode(lightPins[index], OUTPUT); // Set Pin Mode 50 | digitalWrite(lightPins[index], LOW); // Set Light with the LOW state. 51 | } 52 | finiteStateMachine.begin(RED); // FSM begins with Initial Transition Id 0 53 | } 54 | 55 | void loop() { 56 | finiteStateMachine.execute(); // Execute the FSM 57 | } 58 | 59 | void EventOnActionChanged(EventArgs e) { 60 | switch (e.action) { 61 | case ENTRY: 62 | digitalWrite(lightPins[e.id], HIGH); // Set Light with the HIGH state. 63 | break; 64 | case EXIT: 65 | digitalWrite(lightPins[e.id], LOW); // Set Light with the LOW state. 66 | break; 67 | } 68 | } -------------------------------------------------------------------------------- /examples/AuCP_Fan-Control-With-A-Thermostat/AuCP_Fan-Control-With-A-Thermostat.ino: -------------------------------------------------------------------------------- 1 | /* 2 | Sketch: AuCP_Fan-Control-With-A-Thermostat.ino 3 | Created: 17-Apr-2023 4 | Author: MicroBeaut (μB) 5 | GitHub: https://github.com/MicroBeaut/Finite-State#fan-control-with-a-thermostat 6 | */ 7 | 8 | #include "FiniteState.h" 9 | 10 | #define thermostatPin A0 11 | #define startStatusPin 5 12 | #define stopStatusPin 6 13 | 14 | /* 15 | ____________________________________________________________________________________________________________________________________________________ 16 | | State-Transition Table | 17 | |___________________________________________________________________________________________________________________________________________________| 18 | | | | | Next-State | Next-State | | | Delay-Time | | 19 | | State | Id | Predicate | Fase | True | Process | Event | (milliseconds) | Timer-Type | 20 | |_____________|_______|___________________|_____________|_____________|_________________|_______________________|_________________|_________________| 21 | | STOP | 0 | HighTempPredicate | 0 | 1 | FanStopProcess | - | - | - | 22 | | START | 1 | LowTempPredicate | 1 | 0 | FanStartProcess | - | - | - | 23 | |_____________|_______|___________________|_____________|_____________|_________________|_______________________|_________________|_________________| 24 | */ 25 | 26 | void FanStartProcess(id_t id); 27 | void FanStopProcess(id_t id); 28 | bool HighTempPredicate(id_t state); 29 | bool LowTempPredicate(id_t state); 30 | 31 | enum FanState : id_t { 32 | STOP, 33 | START 34 | }; 35 | 36 | Transition transitions[] = { 37 | {HighTempPredicate, STOP, START, FanStopProcess}, // State-0 - NextF = 0, NextT = 1 38 | {LowTempPredicate, START, STOP, FanStartProcess} // State-1 - NextF = 1, NextT = 0 39 | }; 40 | const uint8_t numberOfTransitions = sizeof(transitions) / sizeof(Transition); // Calculate the number of transitions. 41 | 42 | FiniteState finiteStateMachine(transitions, numberOfTransitions); // Finite-State Object 43 | 44 | const long ThermostatRead(); 45 | 46 | void setup() { 47 | pinMode(startStatusPin, OUTPUT); // Set the start status pin mode 48 | pinMode(stopStatusPin, OUTPUT); // Set the sotp status pin mode 49 | finiteStateMachine.begin(STOP); // FSM begins with Initial Transition Id 0 50 | } 51 | 52 | void loop() { 53 | finiteStateMachine.execute(); // Execute the FSM 54 | } 55 | 56 | bool HighTempPredicate(id_t state) { 57 | return ThermostatRead() >= 40; // Determine Fan Start Action 58 | } 59 | 60 | bool LowTempPredicate(id_t state) { 61 | return ThermostatRead() <= 30; // Determine Fan Stop Action 62 | } 63 | 64 | void FanStartProcess(id_t id) { 65 | digitalWrite(stopStatusPin, false); // Update fan stop status 66 | digitalWrite(startStatusPin, true); // Update fan start status 67 | } 68 | 69 | void FanStopProcess(id_t id) { 70 | digitalWrite(startStatusPin, false); // Update fan start status 71 | digitalWrite(stopStatusPin, true); // Update fan stop status 72 | } 73 | 74 | const long ThermostatRead() { 75 | long value = analogRead(thermostatPin); // Read Pushbutton Value 76 | return map(value, 0, 1023, 0, 100); // Scaling temperature 77 | } -------------------------------------------------------------------------------- /examples/AuCP_Debounce/AuCP_Debounce.ino: -------------------------------------------------------------------------------- 1 | /* 2 | AuCP_Debounce.ino 3 | Created: 5-May-2023 4 | Author: MicroBeaut 5 | GitHub: https://github.com/MicroBeaut/Finite-State#debounce 6 | */ 7 | 8 | #include "FiniteState.h" 9 | 10 | #define buttonPin A0 // Define the Button input pin. 11 | #define ledPin 7 // Define the LED output pin. 12 | 13 | /* 14 | __________________________________________________________________________________________________________________________________________________ 15 | | State-Transition Table | 16 | |_________________________________________________________________________________________________________________________________________________| 17 | | | | | Next-State | Next-State | | | Delay-Time | | 18 | | State | Id | Predicate | Fase | True | Process | Event | (milliseconds) | Timer-Type | 19 | |_____________|_______|_________________|_____________|_____________|_________________|_______________________|_________________|_________________| 20 | | RELEASED | 0 | ButtonPredicate | 0 | 1 | ReleasedProcess | - | - | - | 21 | | DEBOUNCE_T | 1 | ButtonPredicate | 0 | 2 | - | - | 10 | TRUE_TIMER | 22 | | PRESSED | 2 | ButtonPredicate | 3 | 2 | PressedProcess | - | - | - | 23 | | DEBOUNCE_F | 3 | ButtonPredicate | 0 | 2 | - | - | 10 | FALSE_TIMER | 24 | |_____________|_______|_________________|_____________|_____________|_________________|_______________________|_________________|_________________| 25 | */ 26 | 27 | bool ButtonPredicate(id_t id); // Declare Read Button Predicate function 28 | void ReleasedProcess(id_t id); // Declare Released Process function 29 | void PressedProcess(id_t id); // Declare Pressed Process function 30 | 31 | enum DebounceState : id_t { 32 | RELEASED, 33 | DEBOUNCE_T, 34 | PRESSED, 35 | DEBOUNCE_F 36 | }; 37 | 38 | #define debounce 10 // Debounce Delay 10 milliseconds 39 | 40 | Transition transitions[] = { 41 | {ButtonPredicate, RELEASED, DEBOUNCE_T, ReleasedProcess}, // State-0 - NextF = 0, NextT = 1 42 | {ButtonPredicate, RELEASED, PRESSED, nullptr, nullptr, debounce, TRUE_TIMER}, // State-1 - NextF = 0, NextT = 2 43 | {ButtonPredicate, DEBOUNCE_F, PRESSED, PressedProcess}, // State-2 - NextF = 3, NextT = 2 44 | {ButtonPredicate, RELEASED, PRESSED, nullptr, nullptr, debounce, FALSE_TIMER} // State-3 - NextF = 0, NextT = 2 45 | }; 46 | const uint8_t numberOfTransitions = sizeof(transitions) / sizeof(Transition); // Calculate the number of transitions. 47 | 48 | FiniteState debounceFS(transitions, numberOfTransitions); // Finite-State Object 49 | bool buttonState; 50 | 51 | void setup() { 52 | pinMode(buttonPin, INPUT_PULLUP); // Set the Button input mode 53 | pinMode(ledPin, OUTPUT); // Set the LED output pin mode 54 | debounceFS.begin(RELEASED); // FSM begins with Initial Transition Id 0 55 | } 56 | 57 | void loop() { 58 | debounceFS.execute(); // Execute the FSM 59 | digitalWrite(ledPin, buttonState); // Set LED with the button State. 60 | } 61 | 62 | bool ButtonPredicate(id_t id) { 63 | return !digitalRead(buttonPin); // Read Button value. 64 | } 65 | 66 | void ReleasedProcess(id_t id) { 67 | buttonState = false; // Set the Button state with false value. 68 | } 69 | 70 | void PressedProcess(id_t id) { 71 | buttonState = true; // Set the Button state with true value. 72 | } -------------------------------------------------------------------------------- /examples/AuCP_Traffic-Light/AuCP_Traffic-Light.ino: -------------------------------------------------------------------------------- 1 | /* 2 | Sketch: AuCP_Traffic-Light.ino 3 | Created: 17-Apr-2023 4 | Author: MicroBeaut (μB) 5 | GitHub: https://github.com/MicroBeaut/Finite-State#traffic-light-with-customized-timer-not_used 6 | */ 7 | 8 | #include "FiniteState.h" 9 | 10 | #define redLightPin 5 11 | #define yellowLightPin 4 12 | #define greenLightPin 3 13 | 14 | uint8_t lightPins[] = {redLightPin, greenLightPin, yellowLightPin}; // Define an array of light pins. 15 | const uint8_t numberOfLights = sizeof(lightPins) / sizeof(uint8_t); // Calculate the number of lights. 16 | 17 | typedef struct { 18 | unsigned long delayTime; 19 | unsigned long startTime; 20 | } Timer; 21 | 22 | Timer delayTimes[] = { 23 | {5000}, // RED Delay Time 5 seconds 24 | {10000}, // GREEN Delay Time 10 seconds 25 | {3000}, // YELLOW Delay Time 3 seconds 26 | }; 27 | 28 | /* 29 | ____________________________________________________________________________________________________________________________________________________ 30 | | State-Transition Table | 31 | |___________________________________________________________________________________________________________________________________________________| 32 | | | | | Next-State | Next-State | | | Delay-Time | | 33 | | State | Id | Predicate | Fase | True | Process | Event | (milliseconds) | Timer-Type | 34 | |_____________|_______|___________________|_____________|_____________|_________________|_______________________|_________________|_________________| 35 | | RED | 0 | TimePredicate | 0 | 1 | - | EventOnActionChanged | - | - | 36 | | GREEN | 1 | TimePredicate | 1 | 2 | - | EventOnActionChanged | - | - | 37 | | YELLOW | 2 | TimePredicate | 2 | 0 | - | EventOnActionChanged | - | - | 38 | |_____________|_______|___________________|_____________|_____________|_________________|_______________________|_________________|_________________| 39 | */ 40 | 41 | bool TimePredicate(id_t id); // Predicate (Input) 42 | void EventOnActionChanged(EventArgs e); // Event State 43 | 44 | enum LightState { 45 | RED, 46 | GREEN, 47 | YELLOW 48 | }; 49 | 50 | Transition transitions[] = { 51 | {TimePredicate, RED, GREEN, nullptr, EventOnActionChanged}, // State-1 - NextF = 0, NextT = 1 52 | {TimePredicate, GREEN, YELLOW, nullptr, EventOnActionChanged}, // State-2 - NextF = 1, NextT = 2 53 | {TimePredicate, YELLOW, RED, nullptr, EventOnActionChanged}, // State-3 - NextF = 2, NextT = 0 54 | }; 55 | const uint8_t numberOfTransitions = sizeof(transitions) / sizeof(Transition); // Calculate the number of transitions. 56 | 57 | FiniteState finiteStateMachine(transitions, numberOfTransitions); // Define Finite-State Object 58 | 59 | void setup() { 60 | for (uint8_t index = 0; index < numberOfLights; index ++) { 61 | pinMode(lightPins[index], OUTPUT); // Set Pin Mode 62 | digitalWrite(lightPins[index], LOW); // Set Light with the LOW state. 63 | } 64 | finiteStateMachine.begin(RED); // FSM begins with Initial Transition Id 0 65 | } 66 | 67 | void loop() { 68 | finiteStateMachine.execute(); // Execute the FSM 69 | } 70 | 71 | bool TimePredicate(id_t id) { 72 | return (millis() - delayTimes[id].startTime >= delayTimes[id].delayTime); // Determine Time Delay 73 | } 74 | 75 | void EventOnActionChanged(EventArgs e) { 76 | switch (e.action) { 77 | case ENTRY: 78 | delayTimes[e.id].startTime = millis(); // Reload start time 79 | digitalWrite(lightPins[e.id], HIGH); // Set Light with the HIGH state. 80 | break; 81 | case EXIT: 82 | digitalWrite(lightPins[e.id], LOW); // Set Light with the LOW state. 83 | break; 84 | } 85 | } -------------------------------------------------------------------------------- /examples/AuCP_Coin-Operated-Turnstile-With-Event/AuCP_Coin-Operated-Turnstile-With-Event.ino: -------------------------------------------------------------------------------- 1 | /* 2 | AuCP_Coin-Operated-Turnstile-With-Event.ino 3 | Created: 4-May-2023 4 | Author: MicroBeaut 5 | GitHub: https://github.com/MicroBeaut/Finite-State#coin-operated-turnstile-with-predicate-and-event 6 | */ 7 | 8 | #include "FiniteState.h" 9 | #include "RepeatButton.h" 10 | 11 | #define coinInputPin A0 // Define the Coin input pin. 12 | #define armInputPin A1 // Define the Push input pin. 13 | 14 | #define lockedStatusPin 7 // Define the Locked state output pin. 15 | #define unlockedStatusPin 6 // Define the Unlocked state output pin. 16 | 17 | /* 18 | ____________________________________________________________________________________________________________________________________________________ 19 | | State-Transition Table | 20 | |___________________________________________________________________________________________________________________________________________________| 21 | | | | | Next-State | Next-State | | | Delay-Time | | 22 | | State | Id | Predicate | Fase | True | Process | Event | (milliseconds) | Timer-Type | 23 | |_____________|_______|___________________|_____________|_____________|_________________|_______________________|_________________|_________________| 24 | | LOCKED | 0 | CoinPredicate | 0 | 1 | - | EventOnActionChanged | - | - | 25 | | UNLOCKED | 1 | ArmPredicate | 1 | 0 | - | EventOnActionChanged | - | - | 26 | |_____________|_______|___________________|_____________|_____________|_________________|_______________________|_________________|_________________| 27 | */ 28 | 29 | bool inputPredicate(id_t id); // Declare Coin Predicate function 30 | void EventOnActionChanged(EventArgs e); // Event On Action Changed 31 | 32 | enum TurnstileState : id_t { 33 | LOCKED, 34 | UNLOCKED 35 | }; 36 | 37 | Transition transitions[] = { 38 | {inputPredicate, LOCKED, UNLOCKED, nullptr, EventOnActionChanged}, // State-0 - NextF = 0, NextT = 1 39 | {inputPredicate, UNLOCKED, LOCKED, nullptr, EventOnActionChanged} // State-1 - NextF = 1, NextT = 0 40 | }; 41 | const uint8_t numberOfTransitions = sizeof(transitions) / sizeof(Transition); // Calculate the number of transitions. 42 | 43 | FiniteState coinOperatedTurnstile(transitions, numberOfTransitions); // Finite-State Object 44 | 45 | uint8_t inputPins[numberOfTransitions] = {coinInputPin, armInputPin}; // Declare the input pin array 46 | uint8_t outputPins[numberOfTransitions] = {lockedStatusPin, unlockedStatusPin}; // Declare the output pin array 47 | RepeatButton turnstileInputs[numberOfTransitions]; // Declare the Turnstile Inputs RepeatButton object 48 | 49 | void setup() { 50 | for (uint8_t index = 0; index < numberOfTransitions; index++) { 51 | turnstileInputs[index].buttonMode(inputPins[index], INPUT_PULLUP); // Set the Turnstile repeat button pin mode 52 | pinMode(outputPins[index], OUTPUT); // Set the Output state pin mode 53 | } 54 | coinOperatedTurnstile.begin(LOCKED); // FSM begins with Initial Transition Id 0 55 | } 56 | 57 | void loop() { 58 | for (uint8_t index = 0; index < numberOfTransitions; index++) { 59 | turnstileInputs[index].repeatButton(); // Executing the Turnstile repeat button function. 60 | } 61 | coinOperatedTurnstile.execute(); // Execute the FSM. 62 | } 63 | 64 | bool inputPredicate(id_t id) { 65 | return turnstileInputs[id].isPressed(); // Predicate putting a coin and pushing the arm. 66 | } 67 | 68 | void EventOnActionChanged(EventArgs e) { 69 | switch (e.action) { 70 | case ENTRY: 71 | digitalWrite(outputPins[e.id], HIGH); // Turn on the turnstile position status. 72 | break; 73 | case EXIT: 74 | digitalWrite(outputPins[e.id], LOW); // Turn off the previous turnstile position status. 75 | break; 76 | } 77 | } -------------------------------------------------------------------------------- /examples/AuCP_Coin-Operated-Turnstile/AuCP_Coin-Operated-Turnstile.ino: -------------------------------------------------------------------------------- 1 | /* 2 | AuCP_Coin-Operated-Turnstile.ino 3 | Created: 4-May-2023 4 | Author: MicroBeaut 5 | GitHub: https://github.com/MicroBeaut/Finite-State#coin-operated-turnstile-with-predicate-and-process 6 | */ 7 | 8 | #include "FiniteState.h" 9 | #include "RepeatButton.h" 10 | 11 | #define coinInputPin A0 // Define the Coin input pin. 12 | #define armInputPin A1 // Define the Arm input pin. 13 | 14 | #define lockedStatusPin 7 // Define the Locked state output pin. 15 | #define unlockedStatusPin 6 // Define the Unlocked state output pin. 16 | 17 | /* 18 | ____________________________________________________________________________________________________________________________________________________ 19 | | State-Transition Table | 20 | |___________________________________________________________________________________________________________________________________________________| 21 | | | | | Next-State | Next-State | | | Delay-Time | | 22 | | State | Id | Predicate | Fase | True | Process | Event | (milliseconds) | Timer-Type | 23 | |_____________|_______|___________________|_____________|_____________|_________________|_______________________|_________________|_________________| 24 | | LOCKED | 0 | CoinPredicate | 0 | 1 | LockedProcess | - | - | - | 25 | | UNLOCKED | 1 | ArmPredicate | 1 | 0 | UnlockedProcess | - | - | - | 26 | |_____________|_______|___________________|_____________|_____________|_________________|_______________________|_________________|_________________| 27 | */ 28 | 29 | bool CoinPredicate(id_t id); // Declare Coin Predicate function 30 | bool ArmPredicate(id_t id); // Declare Arm Predicate function 31 | 32 | void LockedProcess(id_t id); // Declare Locked Process function 33 | void UnlockedProcess(id_t id); // Declare Unlocked Process function 34 | 35 | enum TurnstileState : id_t { 36 | LOCKED, 37 | UNLOCKED 38 | }; 39 | 40 | Transition transitions[] = { 41 | {CoinPredicate, LOCKED, UNLOCKED, LockedProcess}, // State-0 - NextF = 0, NextT = 1 42 | {ArmPredicate, UNLOCKED, LOCKED, UnlockedProcess} // State-1 - NextF = 1, NextT = 0 43 | }; 44 | const uint8_t numberOfTransitions = sizeof(transitions) / sizeof(Transition); // Calculate the number of transitions. 45 | 46 | FiniteState coinOperatedTurnstile(transitions, numberOfTransitions); // Finite-State Object 47 | 48 | RepeatButton coin; // Declare the Coin RepeatButton object 49 | RepeatButton arm; // Declare the Arm RepeatButton object 50 | 51 | void setup() { 52 | coin.buttonMode(coinInputPin, INPUT_PULLUP); // Set the Coin input pin mode 53 | arm.buttonMode(armInputPin, INPUT_PULLUP); // Set the Arm input pin mode 54 | pinMode(lockedStatusPin, OUTPUT); // Set the Locked state pin mode 55 | pinMode(unlockedStatusPin, OUTPUT); // Set the Unlocked state pin mode 56 | 57 | coinOperatedTurnstile.begin(LOCKED); // FSM begins with Initial Transition Id 0 58 | } 59 | 60 | void loop() { 61 | coin.repeatButton(); // Executing the Coin repeat button function 62 | arm.repeatButton(); // Executing the Arm repeat button function 63 | coinOperatedTurnstile.execute(); // Execute the FSM 64 | } 65 | 66 | bool CoinPredicate(id_t id) { 67 | return coin.isPressed(); // Predicate putting a coin. 68 | } 69 | 70 | bool ArmPredicate(id_t id) { 71 | return arm.isPressed(); // Predicate pushing the arm. 72 | } 73 | 74 | void LockedProcess(id_t id) { 75 | digitalWrite(lockedStatusPin, HIGH); // Turn on the locked position status. 76 | digitalWrite(unlockedStatusPin, LOW); // Turn off the unlocked position status. 77 | } 78 | 79 | void UnlockedProcess(id_t id) { 80 | digitalWrite(lockedStatusPin, LOW); // Turn off the locked position status. 81 | digitalWrite(unlockedStatusPin, HIGH); // Turn on the unlocked position status. 82 | } -------------------------------------------------------------------------------- /src/FiniteState.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | FiniteState.cpp 3 | Created: 14-Apr-2023 4 | Author: MicroBeaut 5 | 6 | MIT License 7 | Copyright (c) 2023 MicroBeaut 8 | */ 9 | 10 | #include "FiniteState.h" 11 | 12 | FiniteState::FiniteState(Transition *transitions, const uint8_t numberOfTransitions): size(_size), id(_eventArgs.id) { 13 | _size = this->InternalLimit(numberOfTransitions, STATE_TRANSITION_MIN, STATE_TRANSITION_MAX); 14 | _transitions = transitions; 15 | _eventArgs.id = 0; 16 | _eventArgs.action = NONE; 17 | } 18 | 19 | void FiniteState::begin(const id_t id) { 20 | if (this->InternalBadId(id)) return; 21 | this->InternalEntryAction(id); 22 | } 23 | 24 | void FiniteState::transition(const id_t id) { 25 | if (this->InternalBadId(id)) return; 26 | this->InternalNextStateAction(id); 27 | } 28 | 29 | void FiniteState::execute() { 30 | this->InternalTimerCondition(); 31 | this->InternalProcess(); 32 | } 33 | 34 | void FiniteState::InternalTimerCondition() { 35 | TimerType timerType = _transitions[_eventArgs.id].timerType; 36 | switch (timerType) { 37 | case NOT_USED: 38 | this->InternalNotUsedTimerCondition(); 39 | break; 40 | case TRANS_TIMER: 41 | this->InternalTransitionTimerCondition(); 42 | break; 43 | case PREDIC_TIMER: 44 | this->InternalPredicateTimerCondition(); 45 | break; 46 | case FALSE_TIMER: 47 | this->InternalFalseStateTimerCondition(); 48 | break; 49 | case TRUE_TIMER: 50 | this->InternalTrueStateTimerCondition(); 51 | break; 52 | } 53 | } 54 | 55 | void FiniteState::InternalProcess() { 56 | if (_transitions[_eventArgs.id].process) { 57 | _transitions[_eventArgs.id].process(_eventArgs.id); 58 | } 59 | } 60 | 61 | void FiniteState::InternalNotUsedTimerCondition() { 62 | TriState predicateState = this->InternalPredicate(); 63 | this->InternalNextState(predicateState); 64 | } 65 | 66 | void FiniteState::InternalTransitionTimerCondition() { 67 | TriState timerState = this->InternalTimer(); 68 | switch (timerState) { 69 | case True: 70 | this->InternalNextState(True); 71 | break; 72 | } 73 | } 74 | 75 | void FiniteState::InternalPredicateTimerCondition() { 76 | TriState timerState = this->InternalTimer(); 77 | switch (timerState) { 78 | case True: 79 | TriState predicateState = this->InternalPredicate(); 80 | this->InternalNextState(predicateState); 81 | break; 82 | } 83 | } 84 | 85 | void FiniteState::InternalFalseStateTimerCondition() { 86 | TriState predicateState = this->InternalPredicate(); 87 | TriState timerState = this->InternalTimer(); 88 | switch (predicateState) { 89 | case False: 90 | if (timerState == True) this->InternalNextState(False); 91 | break; 92 | case True: 93 | this->InternalNextState(True); 94 | break; 95 | } 96 | } 97 | 98 | void FiniteState::InternalTrueStateTimerCondition() { 99 | TriState predicateState = this->InternalPredicate(); 100 | TriState timerState = this->InternalTimer(); 101 | switch (predicateState) { 102 | case False: 103 | this->InternalNextState(False); 104 | break; 105 | case True: 106 | if (timerState == True) this->InternalNextState(True); 107 | break; 108 | } 109 | } 110 | 111 | const TriState FiniteState::InternalPredicate() { 112 | if (_transitions[_eventArgs.id].predicate) { 113 | bool state = _transitions[_eventArgs.id].predicate(_eventArgs.id); 114 | return state ? True : False; 115 | } 116 | return Unspecified; 117 | } 118 | 119 | void FiniteState::InternalNextState(TriState state) { 120 | switch (state) { 121 | case False: 122 | this->InternalNextStateAction(_transitions[_eventArgs.id].nextF); 123 | break; 124 | case True: 125 | this->InternalNextStateAction(_transitions[_eventArgs.id].nextT); 126 | break; 127 | } 128 | } 129 | 130 | void FiniteState::InternalNextStateAction(const id_t id) { 131 | if (_eventArgs.id == id) return; 132 | this->InternalExitAction(); 133 | this->InternalEntryAction(id); 134 | } 135 | 136 | void FiniteState::InternalEntryAction(const id_t id) { 137 | _startTime = millis(); 138 | _timeout = false; 139 | _eventArgs.id = id; 140 | this->InternalEventHandler(ENTRY); 141 | } 142 | 143 | void FiniteState::InternalExitAction() { 144 | this->InternalEventHandler(EXIT); 145 | } 146 | 147 | void FiniteState::InternalEventHandler(const Action e) { 148 | if (_eventArgs.action == e) return; 149 | _eventArgs.action = e; 150 | if (_transitions[_eventArgs.id].eventHandler) { 151 | _transitions[_eventArgs.id].eventHandler(_eventArgs); 152 | } 153 | _eventArgs.action = NONE; 154 | } 155 | 156 | const TriState FiniteState::InternalTimer() { 157 | if (_transitions[_eventArgs.id].delayTime < 1) return Unspecified; 158 | bool timeout = this->InternalTimeout(); 159 | return timeout ? True : False; 160 | } 161 | 162 | const bool FiniteState::InternalTimeout() { 163 | if (_timeout) return true; 164 | time_t elapsedTime = millis() - _startTime; 165 | if (elapsedTime < _transitions[_eventArgs.id].delayTime) return false; 166 | _timeout = true; 167 | return true; 168 | } 169 | 170 | const bool FiniteState::InternalBadId(id_t id) { 171 | if (id < _size) return false; 172 | return true; 173 | } 174 | 175 | const uint8_t FiniteState::InternalLimit(const uint8_t value, const uint8_t min, const uint8_t max) { 176 | if (value < min) return min; 177 | if (value > max) return max; 178 | return value; 179 | } -------------------------------------------------------------------------------- /examples/AuCP_Analog-High-Alarm/AuCP_Analog-High-Alarm.ino: -------------------------------------------------------------------------------- 1 | /* 2 | Sketch: AuCP_Analog-High-Alarm.ino 3 | Created: 3-May-2023 4 | Author: MicroBeaut (μB) 5 | GitHub: https://github.com/MicroBeaut/Finite-State#analog-high-alarm 6 | */ 7 | 8 | #include "FiniteState.h" 9 | 10 | #define processValuePin A0 // Define the Process value input pin. 11 | #define normalPin 6 // Define the normal status output pin. 12 | #define preAlarmPin 5 // Define the pre-alarm status output pin. 13 | #define highAlarmPin 4 // Define the high-alarm status output pin. 14 | 15 | enum Operator { 16 | LT, // Less than operator 17 | LE, // Less than or equal operator 18 | GT, // Greater than operator 19 | GE // Greater than or equal operator 20 | }; 21 | 22 | const long setpoint = 85; // Alarm Setpoint 23 | const long deadband = 5; // Alarm Deadband 24 | 25 | Operator operators [] = {GE, GE, LT}; // Comparison operators 26 | long setpoints [] = {setpoint, setpoint, setpoint - deadband}; // Comparison setpoints 27 | 28 | const long AnalogRead(); // Declare Analog Read Function 29 | void ProcessAlarmStatus(bool normal, bool preAlarm, bool highAlarm); // Declare Process Alarm Status Function 30 | 31 | long processValue; // Declare processValue variable 32 | 33 | /* 34 | ____________________________________________________________________________________________________________________________________________________ 35 | | State-Transition Table | 36 | |___________________________________________________________________________________________________________________________________________________| 37 | | | | | Next-State | Next-State | | | Delay-Time | | 38 | | State | Id | Predicate | Fase | True | Process | Event | (milliseconds) | Timer-Type | 39 | |_____________|_______|___________________|_____________|_____________|_________________|_______________________|_________________|_________________| 40 | | NORMAL | 0 | AnalogPredicate | 0 | 1 | NormalProcess | - | - | - | 41 | | PRE_ALARM | 1 | AnalogPredicate | 0 | 2 | PreAlarmProcess | - | 3,000 | TRUE_TIMER | 42 | | HIGH_ALARM | 2 | AnalogPredicate | 2 | 0 | HighAlarmProcess| - | - | - | 43 | |_____________|_______|___________________|_____________|_____________|_________________|_______________________|_________________|_________________| 44 | */ 45 | 46 | bool AnalogPredicate(id_t id); // Declare analog predicate Function 47 | void NormalProcess(id_t id); // Declare normal process Function 48 | void PreAlarmProcess(id_t id); // Declare pre-alarm process Function 49 | void HighAlarmProcess(id_t id); // Declare high-alarm process Function 50 | 51 | enum AnalogState : id_t { 52 | NORMAL, 53 | PRE_ALARM, 54 | HIGH_ALARM 55 | }; 56 | 57 | #define alarmDelay 3000 // Define alarm dalay 58 | 59 | Transition transitions[] = { 60 | {AnalogPredicate, NORMAL, PRE_ALARM, NormalProcess}, // State-0 - NextF = 0, NextT = 1 61 | {AnalogPredicate, NORMAL, HIGH_ALARM, PreAlarmProcess, nullptr, alarmDelay, TRUE_TIMER}, // State-1 - NextF = 0, NextT = 2 62 | {AnalogPredicate, HIGH_ALARM, NORMAL, HighAlarmProcess} // State-2 - NextF = 2, NextT = 0 63 | }; 64 | const uint8_t numberOfTransitions = sizeof(transitions) / sizeof(Transition); // Calculate the number of transitions. 65 | 66 | FiniteState finiteStateMachine(transitions, numberOfTransitions); // Finite-State Object 67 | 68 | void setup() { 69 | pinMode(normalPin, OUTPUT); // Set the normal LED pin mode 70 | pinMode(preAlarmPin, OUTPUT); // Set the pre-alarm LED pin mode 71 | pinMode(highAlarmPin, OUTPUT); // Set the hith-alarm LED= pin mode 72 | finiteStateMachine.begin(NORMAL); // FSM begins with Initial Transition Id 0 73 | } 74 | 75 | void loop() { 76 | finiteStateMachine.execute(); // Execute the FSM 77 | processValue = AnalogRead(); // Read processValue 78 | } 79 | 80 | void NormalProcess(id_t id) { 81 | ProcessAlarmStatus(true, false, false); // Update process alarm status 82 | } 83 | 84 | void PreAlarmProcess(id_t id) { 85 | ProcessAlarmStatus(false, true, false); // Update process alarm status 86 | } 87 | 88 | void HighAlarmProcess(id_t id) { 89 | ProcessAlarmStatus(false, true, true); // Update process alarm status 90 | } 91 | 92 | bool AnalogPredicate(id_t id) { 93 | bool value; 94 | switch (operators[id]) { 95 | case GE: 96 | value = processValue >= setpoints[id]; // Compare process value with setpoint 97 | break; 98 | case LT: 99 | value = processValue < setpoints[id]; // Compare process value with setpoint 100 | break; 101 | default: 102 | value = false; 103 | break; 104 | } 105 | return value; 106 | } 107 | 108 | void ProcessAlarmStatus(bool normal, bool preAlarm, bool highAlarm) { 109 | digitalWrite(normalPin, normal); // Update normal status 110 | digitalWrite(preAlarmPin, preAlarm); // Update pre-alarm status 111 | digitalWrite(highAlarmPin, highAlarm); // Update high-alarm status 112 | } 113 | 114 | const long AnalogRead() { 115 | long value = analogRead(processValuePin); // Read Process Value 116 | return map(value, 0, 1023, 0, 100); // Scaling processValue 117 | } -------------------------------------------------------------------------------- /images/wokwi-sim/wokwi-simulate-black.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 7 | 8 | 9 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | Page-1 30 | 32 | 33 | Sheet.19 34 | MicroBeaut 35 | 36 | 37 | 38 | MicroBeaut 39 | 40 | Sheet.10 41 | 44 | 45 | 46 | Sheet.12 47 | Sim 48 | 49 | 50 | 51 | Sim 52 | 53 | Sheet.6 54 | Sim 55 | 56 | 57 | 58 | Sim 59 | 60 | Sheet.11 61 | 62 | Sheet.8 63 | 75 | 76 | 77 | Sheet.9 78 | 87 | 88 | 89 | 90 | 91 | -------------------------------------------------------------------------------- /images/Transition-Member.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 7 | 8 | 9 | 24 | 25 | 26 | Page-1 27 | 29 | 30 | 31 | 32 | External interactor 33 | Predicate 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | Predicate 46 | 47 | External interactor.6 48 | Next State 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | Next State 61 | 62 | External interactor.9 63 | Event 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | Event 76 | 77 | External interactor.12 78 | Process 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | Process 91 | 92 | External interactor.21 93 | Timer 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | Timer 106 | 108 | Center to center 1 109 | 110 | 111 | 112 | 113 | 114 | 115 | 117 | Center to center 1.25 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | Center to center 1.27 126 | 127 | 128 | 129 | 130 | 131 | 132 | 134 | Center to center 1.28 135 | 136 | 137 | 138 | 139 | 140 | 141 | 143 | Center to center 1.29 144 | 145 | 146 | 147 | 148 | 149 | 150 | 151 | 152 | 153 | 154 | 155 | 156 | 157 | 158 | 159 | Multi state 160 | Transition 161 | 162 | Sheet.31 163 | 164 | 165 | 166 | Sheet.32 167 | 168 | 169 | 170 | 171 | 172 | Transition 173 | 174 | 175 | 176 | -------------------------------------------------------------------------------- /images/example/Fan-Control-With-A-Thermostat.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 7 | 8 | 9 | 24 | 25 | 26 | 27 | 28 | 29 | 31 | 32 | 33 | 35 | 36 | 37 | 38 | 39 | Page-1 40 | 42 | 43 | 44 | 45 | Center to center 1 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | Center to center 1.17 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | Loop on center 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | Sheet.23 70 | T < 40 °C 71 | 72 | 73 | 74 | T < 40 °C 76 | 77 | Sheet.25 78 | T ≥ 40 °C 79 | 80 | 81 | 82 | T ≥ 40 °C 83 | 84 | Sheet.26 85 | T ≤ 30 °C 86 | 87 | 88 | 89 | T ≤ 30 °C 90 | 91 | Sheet.37 92 | T > 30 °C 93 | 94 | 95 | 96 | T > 30 °C 97 | 98 | State.38 99 | S1 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | S1 113 | 114 | Sheet.39 115 | TEMP. 116 | 117 | 118 | 119 | TEMP. 120 | 121 | Sheet.40 122 | START 123 | 124 | 125 | 126 | START 127 | 128 | State.42 129 | S0 130 | 131 | 132 | 133 | 134 | 135 | 136 | 137 | 138 | 139 | 140 | 141 | S0 143 | 144 | Sheet.43 145 | STOP 146 | 147 | 148 | 149 | STOP 150 | 151 | Sheet.44 152 | TEMP. 153 | 154 | 155 | 156 | TEMP. 157 | 158 | Loop on center.119 159 | 160 | 161 | 162 | 163 | 164 | 165 | 166 | 167 | -------------------------------------------------------------------------------- /images/example/Coin-Operated-Turnstile.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 7 | 8 | 9 | 25 | 26 | 27 | 28 | 29 | 30 | 32 | 33 | 34 | 36 | 37 | 38 | 39 | 40 | Page-1 41 | 43 | 44 | 45 | 46 | State.331 47 | S0 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | S0 61 | 62 | Center to center 1.332 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | Center to center 1.333 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | Sheet.48 79 | Inserted 80 | 81 | 82 | 83 | Inserted 85 | 86 | State.335 87 | S1 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | S1 101 | 102 | Loop on center.336 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | Loop on center.337 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | Sheet.52 119 | Pushed 120 | 121 | 122 | 123 | Pushed 125 | 126 | Sheet.53 127 | Waiting 128 | 129 | 130 | 131 | Waiting 132 | 133 | Sheet.54 134 | Waiting 135 | 136 | 137 | 138 | Waiting 140 | 141 | Sheet.55 142 | LOCKED 143 | 144 | 145 | 146 | LOCKED 148 | 149 | Sheet.56 150 | COIN 151 | 152 | 153 | 154 | COIN 156 | 157 | Sheet.57 158 | UNLOCKED 159 | 160 | 161 | 162 | UNLOCKED 164 | 165 | Sheet.58 166 | ARM 167 | 168 | 169 | 170 | ARM 172 | 173 | 174 | -------------------------------------------------------------------------------- /images/timer-type/not-used-timer/option2-predicate-with-process.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 7 | 8 | 9 | 25 | 26 | 27 | 28 | 29 | 30 | 32 | 33 | 34 | 36 | 37 | 38 | 39 | 40 | Page-1 41 | 43 | 44 | 45 | 46 | Center to center 1.332 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | Center to center 1.333 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | Sheet.334 63 | TRUE 64 | 65 | 66 | 67 | TRUE 69 | 71 | Loop on center.336 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | Loop on center.337 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | Sheet.338 88 | TRUE 89 | 90 | 91 | 92 | TRUE 94 | 95 | Sheet.339 96 | FALSE 97 | 98 | 99 | 100 | FALSE 101 | 102 | Sheet.340 103 | FALSE 104 | 105 | 106 | 107 | FALSE 109 | 110 | State.331 111 | S0 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | S0 125 | 127 | State.335 128 | S1 129 | 130 | 131 | 132 | 133 | 134 | 135 | 136 | 137 | 138 | 139 | 140 | S1 142 | 143 | Sheet.341 144 | PROCESS 145 | 146 | 147 | 148 | PROCESS 150 | 151 | Sheet.342 152 | PREDICATE 153 | 154 | 155 | 156 | PREDICATE 158 | 159 | Sheet.343 160 | PROCESS 161 | 162 | 163 | 164 | PROCESS 166 | 167 | Sheet.344 168 | PREDICATE 169 | 170 | 171 | 172 | PREDICATE 174 | 175 | 176 | -------------------------------------------------------------------------------- /images/timer-type/transition-timer/option2-transition-timer-with-process.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 7 | 8 | 9 | 27 | 28 | 29 | 30 | 31 | 32 | 34 | 35 | 36 | 38 | 39 | 40 | 41 | 42 | Page-1 43 | 45 | 46 | 47 | 48 | Center to center 1.397 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | Center to center 1.398 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | Sheet.527 65 | TRUE 66 | 67 | 68 | 69 | TRUE 71 | 73 | Loop on center.402 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | Loop on center.404 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | Sheet.531 90 | TRUE 91 | 92 | 93 | 94 | TRUE 96 | 97 | Sheet.534 98 | T < 1S 99 | 100 | 101 | 102 | T < 1S 104 | 105 | Sheet.535 106 | T < 1S 107 | 108 | 109 | 110 | T < 1S 112 | 113 | Sheet.536 114 | TTR-T 115 | 116 | 117 | 118 | TTR-T 122 | 123 | Sheet.537 124 | TTR-T 125 | 126 | 127 | 128 | TTR-T 132 | 133 | State.396 134 | S0 135 | 136 | 137 | 138 | 139 | 140 | 141 | 142 | 143 | 144 | 145 | 146 | S0 148 | 150 | State.400 151 | S1 152 | 153 | 154 | 155 | 156 | 157 | 158 | 159 | 160 | 161 | 162 | 163 | S1 165 | 166 | Sheet.532 167 | PROCESS 168 | 169 | 170 | 171 | PROCESS 173 | 174 | Sheet.533 175 | PROCESS 176 | 177 | 178 | 179 | PROCESS 181 | 182 | 183 | -------------------------------------------------------------------------------- /images/example/Blink.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 7 | 8 | 9 | 28 | 29 | 30 | 31 | 32 | 33 | 35 | 36 | 37 | 39 | 40 | 41 | 42 | 43 | Page-1 44 | 46 | 47 | 48 | 49 | State.396 50 | S0 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | S0 64 | 65 | Center to center 1.397 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | Center to center 1.398 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | Sheet.103 82 | TRUE 83 | 84 | 85 | 86 | TRUE 88 | 90 | State.400 91 | S1 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | S1 105 | 107 | Loop on center.402 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | Loop on center.404 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | Sheet.107 124 | TRUE 125 | 126 | 127 | 128 | TRUE 130 | 131 | Sheet.108 132 | LED-OFF 133 | 134 | 135 | 136 | LED-OFF 138 | 139 | Sheet.109 140 | LED-ON 141 | 142 | 143 | 144 | LED-ON 146 | 147 | Sheet.111 148 | T < 1S 149 | 150 | 151 | 152 | T < 1S 154 | 155 | Sheet.112 156 | TTR-T 157 | 158 | 159 | 160 | TTR-T 164 | 165 | Sheet.113 166 | TTR-T 167 | 168 | 169 | 170 | TTR-T 174 | 175 | Sheet.117 176 | T < 0.5S 177 | 178 | 179 | 180 | T < 0.5S 182 | 183 | 184 | -------------------------------------------------------------------------------- /images/timer-type/not-used-timer/option3-predicate-with-event.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 7 | 8 | 9 | 25 | 26 | 27 | 28 | 29 | 30 | 32 | 33 | 34 | 36 | 37 | 38 | 39 | 40 | Page-1 41 | 43 | 44 | 45 | 46 | Center to center 1.314 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | Center to center 1.315 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | Sheet.316 63 | TRUE 64 | 65 | 66 | 67 | TRUE 69 | 70 | Sheet.318 71 | ENTRY 72 | 73 | 74 | 75 | ENTRY 77 | 79 | Loop on center.319 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | Sheet.320 88 | EXIT 89 | 90 | 91 | 92 | EXIT 94 | 95 | Loop on center.321 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | Sheet.322 104 | TRUE 105 | 106 | 107 | 108 | TRUE 110 | 111 | Sheet.323 112 | FALSE 113 | 114 | 115 | 116 | FALSE 117 | 118 | Sheet.324 119 | FALSE 120 | 121 | 122 | 123 | FALSE 125 | 126 | Sheet.329 127 | ENTRY 128 | 129 | 130 | 131 | ENTRY 133 | 134 | Sheet.330 135 | EXIT 136 | 137 | 138 | 139 | EXIT 141 | 142 | State.313 143 | S0 144 | 145 | 146 | 147 | 148 | 149 | 150 | 151 | 152 | 153 | 154 | 155 | S0 157 | 159 | State.317 160 | S1 161 | 162 | 163 | 164 | 165 | 166 | 167 | 168 | 169 | 170 | 171 | 172 | S1 174 | 175 | Sheet.326 176 | PREDICATE 177 | 178 | 179 | 180 | PREDICATE 182 | 183 | Sheet.328 184 | PREDICATE 185 | 186 | 187 | 188 | PREDICATE 190 | 191 | 192 | -------------------------------------------------------------------------------- /images/timer-type/transition-timer/option3-transition-timer-with-event.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 7 | 8 | 9 | 27 | 28 | 29 | 30 | 31 | 32 | 34 | 35 | 36 | 38 | 39 | 40 | 41 | 42 | Page-1 43 | 45 | 46 | 47 | 48 | Center to center 1.415 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | Center to center 1.416 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | Sheet.541 65 | TRUE 66 | 67 | 68 | 69 | TRUE 71 | 72 | Sheet.543 73 | ENTRY 74 | 75 | 76 | 77 | ENTRY 79 | 81 | Loop on center.420 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | Sheet.545 90 | EXIT 91 | 92 | 93 | 94 | EXIT 96 | 97 | Loop on center.422 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | Sheet.547 106 | TRUE 107 | 108 | 109 | 110 | TRUE 112 | 113 | Sheet.548 114 | ENTRY 115 | 116 | 117 | 118 | ENTRY 120 | 121 | Sheet.549 122 | EXIT 123 | 124 | 125 | 126 | EXIT 128 | 129 | Sheet.550 130 | T < 1S 131 | 132 | 133 | 134 | T < 1S 136 | 137 | Sheet.551 138 | T < 1S 139 | 140 | 141 | 142 | T < 1S 144 | 145 | Sheet.552 146 | TTR-T 147 | 148 | 149 | 150 | TTR-T 154 | 155 | Sheet.553 156 | TTR-T 157 | 158 | 159 | 160 | TTR-T 164 | 165 | State.414 166 | S0 167 | 168 | 169 | 170 | 171 | 172 | 173 | 174 | 175 | 176 | 177 | 178 | S0 180 | 182 | State.418 183 | S1 184 | 185 | 186 | 187 | 188 | 189 | 190 | 191 | 192 | 193 | 194 | 195 | S1 197 | 198 | 199 | -------------------------------------------------------------------------------- /images/example/Coin-Operated-Turnstile-With-Event.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 7 | 8 | 9 | 26 | 27 | 28 | 29 | 30 | 31 | 33 | 34 | 35 | 37 | 38 | 39 | 40 | 41 | Page-1 42 | 44 | 45 | 46 | 47 | State.331 48 | S0 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | S0 62 | 63 | Center to center 1.332 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | Center to center 1.333 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | Sheet.52 80 | Inserted 81 | 82 | 83 | 84 | Inserted 86 | 87 | State.335 88 | S1 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | S1 102 | 103 | Loop on center.336 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | Loop on center.337 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | Sheet.56 120 | Pushed 121 | 122 | 123 | 124 | Pushed 126 | 127 | Sheet.57 128 | Waiting 129 | 130 | 131 | 132 | Waiting 133 | 134 | Sheet.58 135 | Waiting 136 | 137 | 138 | 139 | Waiting 141 | 142 | Sheet.59 143 | LOCKED 144 | 145 | 146 | 147 | LOCKED 149 | 150 | Sheet.60 151 | COIN 152 | 153 | 154 | 155 | COIN 157 | 158 | Sheet.61 159 | UNLOCKED 160 | 161 | 162 | 163 | UNLOCKED 165 | 166 | Sheet.62 167 | ARM 168 | 169 | 170 | 171 | ARM 173 | 174 | Sheet.63 175 | ENTRY 176 | 177 | 178 | 179 | ENTRY 181 | 182 | Sheet.64 183 | EXIT 184 | 185 | 186 | 187 | EXIT 189 | 190 | Sheet.65 191 | ENTRY 192 | 193 | 194 | 195 | ENTRY 197 | 198 | Sheet.66 199 | EXIT 200 | 201 | 202 | 203 | EXIT 205 | 206 | 207 | -------------------------------------------------------------------------------- /images/timer-type/not-used-timer/option1-predicate-with-process-and-event.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 7 | 8 | 9 | 26 | 27 | 28 | 29 | 30 | 31 | 33 | 34 | 35 | 37 | 38 | 39 | 40 | 41 | Page-1 42 | 44 | 45 | 46 | 47 | Center to center 1.262 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | Center to center 1.263 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | Sheet.242 64 | TRUE 65 | 66 | 67 | 68 | TRUE 70 | 71 | Sheet.244 72 | ENTRY 73 | 74 | 75 | 76 | ENTRY 78 | 80 | Loop on center 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | Sheet.246 89 | EXIT 90 | 91 | 92 | 93 | EXIT 95 | 96 | Loop on center.293 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | Sheet.248 105 | TRUE 106 | 107 | 108 | 109 | TRUE 111 | 112 | Sheet.249 113 | FALSE 114 | 115 | 116 | 117 | FALSE 118 | 119 | Sheet.250 120 | FALSE 121 | 122 | 123 | 124 | FALSE 126 | 127 | Sheet.255 128 | ENTRY 129 | 130 | 131 | 132 | ENTRY 134 | 135 | Sheet.256 136 | EXIT 137 | 138 | 139 | 140 | EXIT 142 | 143 | State.193 144 | S0 145 | 146 | 147 | 148 | 149 | 150 | 151 | 152 | 153 | 154 | 155 | 156 | S0 158 | 160 | State.275 161 | S1 162 | 163 | 164 | 165 | 166 | 167 | 168 | 169 | 170 | 171 | 172 | 173 | S1 175 | 176 | Sheet.251 177 | PROCESS 178 | 179 | 180 | 181 | PROCESS 183 | 184 | Sheet.252 185 | PREDICATE 186 | 187 | 188 | 189 | PREDICATE 191 | 192 | Sheet.253 193 | PROCESS 194 | 195 | 196 | 197 | PROCESS 199 | 200 | Sheet.254 201 | PREDICATE 202 | 203 | 204 | 205 | PREDICATE 207 | 208 | 209 | -------------------------------------------------------------------------------- /images/timer-type/not-used-timer/not-used-timer-state-diagram.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 7 | 8 | 9 | 33 | 34 | 35 | 36 | 37 | 38 | 40 | 41 | 42 | 44 | 45 | 46 | 48 | 49 | 50 | 51 | 52 | Page-1 53 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | Start state.259 67 | BEGIN 68 | 69 | Sheet.260 70 | 71 | 72 | 73 | Sheet.261 74 | 75 | 76 | 77 | 78 | 79 | BEGIN 80 | 81 | 83 | Center to center 1.262 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | Stop state.263 100 | NextT 101 | 102 | Sheet.264 103 | 104 | 105 | 106 | Sheet.265 107 | 108 | 109 | 110 | 111 | 112 | NextT 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | Stop state.266 124 | NextF 125 | 126 | Sheet.267 127 | 128 | 129 | 130 | Sheet.268 131 | 132 | 133 | 134 | 135 | 136 | NextF 137 | 138 | 140 | Center to center 1.269 141 | TRUE 142 | 143 | 144 | 145 | 146 | 147 | 148 | 149 | 151 | TRUE 152 | 154 | Center to center 1.270 155 | FALSE 156 | 157 | 158 | 159 | 160 | 161 | 162 | 163 | 165 | FALSE 166 | 167 | Sheet.272 168 | ENTRY 169 | 170 | 171 | 172 | ENTRY 174 | 175 | Sheet.288 176 | EXIT 177 | 178 | 179 | 180 | EXIT 182 | 183 | Sheet.289 184 | EXIT 185 | 186 | 187 | 188 | EXIT 190 | 191 | State.284 192 | S0 193 | 194 | 195 | 196 | 197 | 198 | 199 | 200 | 201 | 202 | 203 | 204 | S0 206 | 207 | Sheet.285 208 | PROCESS 209 | 210 | 211 | 212 | PROCESS 214 | 215 | Sheet.286 216 | PREDICATE 217 | 218 | 219 | 220 | PREDICATE 222 | 223 | 224 | -------------------------------------------------------------------------------- /images/timer-type/transition-timer/option1-transition-timer-with-process-and-event.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 7 | 8 | 9 | 28 | 29 | 30 | 31 | 32 | 33 | 35 | 36 | 37 | 39 | 40 | 41 | 42 | 43 | Page-1 44 | 46 | 47 | 48 | 49 | Center to center 1.240 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | Center to center 1.263 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | Sheet.503 66 | TRUE 67 | 68 | 69 | 70 | TRUE 72 | 73 | Sheet.505 74 | ENTRY 75 | 76 | 77 | 78 | ENTRY 80 | 82 | Loop on center.300 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | Sheet.507 91 | EXIT 92 | 93 | 94 | 95 | EXIT 97 | 98 | Loop on center.293 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | Sheet.509 107 | TRUE 108 | 109 | 110 | 111 | TRUE 113 | 114 | Sheet.512 115 | ENTRY 116 | 117 | 118 | 119 | ENTRY 121 | 122 | Sheet.513 123 | EXIT 124 | 125 | 126 | 127 | EXIT 129 | 130 | Sheet.520 131 | T < 1S 132 | 133 | 134 | 135 | T < 1S 137 | 138 | Sheet.521 139 | T < 1S 140 | 141 | 142 | 143 | T < 1S 145 | 146 | Sheet.522 147 | TTR-T 148 | 149 | 150 | 151 | TTR-T 155 | 156 | Sheet.523 157 | TTR-T 158 | 159 | 160 | 161 | TTR-T 165 | 166 | State.193 167 | S0 168 | 169 | 170 | 171 | 172 | 173 | 174 | 175 | 176 | 177 | 178 | 179 | S0 181 | 183 | State.275 184 | S1 185 | 186 | 187 | 188 | 189 | 190 | 191 | 192 | 193 | 194 | 195 | 196 | S1 198 | 199 | Sheet.510 200 | PROCESS 201 | 202 | 203 | 204 | PROCESS 206 | 207 | Sheet.511 208 | PROCESS 209 | 210 | 211 | 212 | PROCESS 214 | 215 | 216 | -------------------------------------------------------------------------------- /images/timer-type/true-timer/option2-true-timer-with-process.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 7 | 8 | 9 | 28 | 29 | 30 | 31 | 32 | 33 | 35 | 36 | 37 | 39 | 40 | 41 | 42 | 43 | Page-1 44 | 46 | 47 | 48 | 49 | Loop on center.157 50 | 51 | 52 | 53 | 54 | 55 | 56 | 58 | Loop on center.158 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | Loop on center.159 67 | 68 | 69 | 70 | 71 | 72 | 73 | 75 | Loop on center.160 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | Center to center 1.161 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | Center to center 1.162 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | Sheet.163 100 | TRUE 101 | 102 | 103 | 104 | TRUE 106 | 107 | Sheet.166 108 | TRUE 109 | 110 | 111 | 112 | TRUE 114 | 115 | Sheet.167 116 | FALSE 117 | 118 | 119 | 120 | FALSE 121 | 122 | Sheet.168 123 | FALSE 124 | 125 | 126 | 127 | FALSE 129 | 130 | Sheet.171 131 | T < 1S 132 | 133 | 134 | 135 | T < 1S 137 | 138 | Sheet.172 139 | TTRUE 140 | 141 | 142 | 143 | TTRUE 145 | 146 | Sheet.173 147 | TTRUE 148 | 149 | 150 | 151 | TTRUE 153 | 154 | Sheet.174 155 | T < 1S 156 | 157 | 158 | 159 | T < 1S 161 | 162 | State.175 163 | S0 164 | 165 | 166 | 167 | 168 | 169 | 170 | 171 | 172 | 173 | 174 | 175 | S0 177 | 179 | State.178 180 | S1 181 | 182 | 183 | 184 | 185 | 186 | 187 | 188 | 189 | 190 | 191 | 192 | S1 194 | 195 | Sheet.176 196 | PREDICATE 197 | 198 | 199 | 200 | PREDICATE 202 | 203 | Sheet.177 204 | PROCESS 205 | 206 | 207 | 208 | PROCESS 210 | 211 | Sheet.179 212 | PROCESS 213 | 214 | 215 | 216 | PROCESS 218 | 219 | Sheet.180 220 | PREDICATE 221 | 222 | 223 | 224 | PREDICATE 226 | 227 | 228 | --------------------------------------------------------------------------------