/*
* ARDUINO STATE MACHINE 2022 07N
*
*/
#include <avr/sleep.h>.
#include <avr/wdt.h>
#define VERSION "ARDUINO STATE MACHINE 2022 01"
#define DEBUG 0
#if (DEBUG)
#define DEBUGP(x) Serial.print(x)
#define DEBUGN(x) Serial.println(x)
#else
#define DEBUGP(x)
#define DEBUGN(x)
#endif
//HZ Control
#define HZ_SETTING 20
int mainLoop_count;
unsigned long fast_loopTimer; // Time in miliseconds of main control loop
const int hzCount = (1000 / HZ_SETTING) - 1;
const int timeRemind = 1000 / HZ_SETTING;
void (*resetFunc)(void) = 0; //declare reset function @ address 0 call resetFunc(); if you want to reset
int secCount = 0;
#define LED_PIN 13
#define LED_TASK1 3
#define LED_FAN 4
/// --------------TASK 1 用到的變數 ----------------
#define TASK_STATE_INIT 0
#define TASK_STATE_A 1
#define TASK_STATE_B 2
#define TASK_STATE_UNKNOW 255
byte taskStateCurrent=TASK_STATE_INIT;
byte taskStateLast=TASK_STATE_UNKNOW;
unsigned long task1Counter =0; // State A 裡面專用的計數器
unsigned long task1Timer =0; // State A 裡面專用的計時器
/// --------------FAN 風扇模擬器 用到的變數 ----------------
#define FAN_STATE_INIT 0
#define FAN_STATE_OFF 1
#define FAN_STATE_ON 2
#define FAN_STATE_UNKNOW 255
byte fanStateCurrent=FAN_STATE_INIT;
byte fanStateLast=FAN_STATE_UNKNOW;
unsigned long taskCounterFAN =0; // State B裡面專用的計數器
unsigned long taskTimerFAN =0; // State B 裡面專用的計時器
/// --------------TASK 1 的狀態實作 -----------------------------------------------
void task1StateA(){
/// 下面這區只有進來的時候會作一次 -------------------------------
if(taskStateCurrent!=taskStateLast){
/// 顯示一下目前的狀態
Serial.println("Hello I am task1 State A");
/// 把狀態裡面的變數清空
taskStateLast = taskStateCurrent;
task1Counter=0;
task1Timer =0;
}
task1Timer++;
// 狀態A 說要 每秒閃5 次,那就是每100ms 要變換一次燈號
// 目前這個系統跑在20 HZ ( 請參考一下LINE #27 的MACRO 設定 ),所以每1/20 會被呼叫一次
// 所以只要每2次進來執行這個State 1次 就變換一下LED燈的狀態,就可跑到5HZ 的閃滅
if(task1Timer%2 ==0){
digitalWrite(LED_TASK1,!digitalRead(LED_TASK1));
}
//// 假設這個工作要做10 秒, 然後跳到 狀態B
if(task1Timer>= (10*HZ_SETTING)){
taskStateCurrent = TASK_STATE_B;
}
}
void task1StateB(){
/// 下面這區只有進來的時候會作一次 -------------------------------
if(taskStateCurrent!=taskStateLast){
/// 顯示一下目前的狀態
Serial.println("Hello I am task1 State B");
/// 把狀態裡面的變數清空
taskStateLast = taskStateCurrent;
task1Counter=0;
task1Timer =0;
/// 叫風扇開始開啟散熱
fanStateCurrent = FAN_STATE_ON; ///// 這樣就可以調用到其他狀態機的狀態
}
task1Timer++;
// 狀態B 說要 每秒閃1 次,那就是每500ms 要變換一次燈號
// 目前這個系統跑在20 HZ ( 請參考一下LINE #27 的MACRO 設定 ),所以每1/20 會被呼叫一次
// 所以只要每10次進來執行這個State 1次 就變換一下LED燈的狀態,就可跑到 1 HZ 的閃滅
if(task1Timer%10 ==0){
digitalWrite(LED_TASK1,!digitalRead(LED_TASK1));
}
//// 假設這個工作要做10 秒, 然後跳到 狀態A
if(task1Timer>= (10*HZ_SETTING)){
taskStateCurrent = TASK_STATE_A;
}
}
void task1StateInit(){
Serial.println("Hello I am task1 State Init");
taskStateCurrent = TASK_STATE_A;
}
void task1StateUnknow(){
Serial.println("Hello I am task1 State Unknow");
}
/// --------------FAN 風扇的狀態實作 -----------------------------------------------
void fanStateOFF(){
/// 下面這區只有進來的時候會作一次 -------------------------------
if(fanStateCurrent!= fanStateLast){
/// 顯示一下目前的狀態
Serial.println("Hello I am FAN State OFF ");
fanStateLast = fanStateCurrent;
/// 把狀態裡面的變數清空
taskCounterFAN=0;
taskTimerFAN =0;
///關閉風扇 (進來的時候關閉)
digitalWrite(LED_FAN,LOW);
}
taskTimerFAN++;
/// 在這裡等待被TASK1呼叫
}
void fanStateON(){
/// 下面這區只有進來的時候會作一次 -------------------------------
if(fanStateCurrent!= fanStateLast){
/// 顯示一下目前的狀態
Serial.println("Hello I am FAN State ON ~ ON~ ON ~ ");
fanStateLast = fanStateCurrent;
/// 把狀態裡面的變數清空
taskCounterFAN=0;
taskTimerFAN =0;
///開啟風扇 (進來的時候開啟)
digitalWrite(LED_FAN,HIGH);
}
taskTimerFAN++;
///打個5 秒鐘後,回去關閉狀態
if(taskTimerFAN >= (15*HZ_SETTING) ){
fanStateCurrent = FAN_STATE_OFF;
}
}
void fanStateInit(){
Serial.println("Hello I am fanStateInit");
fanStateCurrent = FAN_STATE_OFF;
}
void fanStateUnknow(){
Serial.println("Hello I am fanStateUnknow");
}
void doSM_TASK(){
switch(taskStateCurrent){
case TASK_STATE_INIT:
task1StateInit();
break;
case TASK_STATE_A :
task1StateA();
break;
case TASK_STATE_B :
task1StateB();
break;
default:
task1StateUnknow();
break;
}
}
void doSM_FAN(){
switch(fanStateCurrent){
case FAN_STATE_INIT:
fanStateInit();
break;
case FAN_STATE_ON:
fanStateON();
break;
case FAN_STATE_OFF :
fanStateOFF();
break;
default :
fanStateUnknow();
break;
}
}
void hw_init()
{
// put your setup code here, to run once:
Serial.begin(115200);
pinMode(LED_PIN, OUTPUT);
pinMode(LED_TASK1, OUTPUT);
pinMode(LED_FAN, OUTPUT);
}
void setup()
{
//Setup I/O
hw_init();
//setup WDT
wdt_enable(WDTO_4S);
}
void loop()
{
// system Loop HZ define in #define HZ_SETTING 5
if (millis() - fast_loopTimer > hzCount)
{
fast_loopTimer = millis();
mainLoop_count++;
wdt_reset(); // Reset WDT ...
/// do things
doSM_TASK();
doSM_FAN();
if (mainLoop_count % HZ_SETTING == 0)
{
secCount++;
digitalWrite(LED_PIN,!digitalRead(LED_PIN));
DEBUGP("Sec count : ");
DEBUGN(secCount);
}
// Time Remind for this Loop ---------------------------------------------------------------
DEBUGP("Time Remind ms :");
DEBUGN(timeRemind - (millis()-fast_loopTimer));
}
}