/*
* ARDUINO STATE MACHINE 2022 02
*
*/
//#include <SoftwareSerial.h>
//#include <SerialCommand.h>
#include "SerialCommand.h"
#include <avr/sleep.h>.
#include <avr/wdt.h>
#define VERSION "ARDUINO STATE MACHINE 2022 01"
#define DEBUG 1
#if (DEBUG)
#define DEBUGP(x) Serial.print(x)
#define DEBUGN(x) Serial.println(x)
#else
#define DEBUGP(x)
#define DEBUGN(x)
#endif
SerialCommand SCmd; // The demo SerialCommand object
//HZ Control
#define HZ_SETTING 10
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
#define LED_PIN 13
//----------------- 在這裡定義State 的編號
#define TASK_STATE_INIT 0
#define TASK_STATE_1 1
#define TASK_STATE_2 2
#define TASK_STATE_3 3
#define TASK_STATE_ERROR 100
#define TASK_STATE_UNKNOW 255
byte stateCurrent = TASK_STATE_INIT; /// 初始的狀態
byte stateLast = TASK_STATE_UNKNOW;
unsigned long taskCounter =0; // State 裡面專用的計數器
unsigned long taskTimer =0; // State 裡面專用的計時器
int secCount = 0;
void showStateName(byte st){
switch(st){
case TASK_STATE_INIT:
Serial.println("TASK_STATE_INIT ----------------------------");
break;
case TASK_STATE_1:
Serial.println("TASK_STATE_1 ----------------------------");
break;
case TASK_STATE_2:
Serial.println("TASK_STATE_2 ----------------------------");
break;
case TASK_STATE_3:
Serial.println("TASK_STATE_3 ----------------------------");
break;
case TASK_STATE_ERROR:
Serial.println("TASK_STATE_ERROR");
break;
default:
Serial.println("TASK_STATE_UNKNOW");
break;
}
}
void stateInit(){
/// 下面這區只有進來的時候會作一次 -------------------------------
if(stateCurrent!=stateLast){
/// 顯示一下目前的狀態
showStateName(stateCurrent);
/// 把狀態裡面的變數清空
stateLast =stateCurrent;
taskCounter =0;
taskTimer =0;
}
taskTimer++;
// 2 秒後離開這個狀態
if(taskTimer> 2*HZ_SETTING ){
stateCurrent = TASK_STATE_1;
}
}
void state1(){
/// 下面這區只有進來的時候會作一次 -------------------------------
if(stateCurrent!=stateLast){
/// 顯示一下目前的狀態
showStateName(stateCurrent);
/// 把狀態裡面的變數清空
stateLast =stateCurrent;
taskCounter =0;
taskTimer =0;
/// 故意清0 讓大家看一下
secCount=0;
}
taskTimer++;
// 10 秒後離開這個狀態
if(taskTimer> 10*HZ_SETTING ){
stateCurrent = TASK_STATE_2;
}
}
void state2(){
/// 下面這區只有進來的時候會作一次 -------------------------------
if(stateCurrent!=stateLast){
/// 顯示一下目前的狀態
showStateName(stateCurrent);
/// 把狀態裡面的變數清空
stateLast =stateCurrent;
taskCounter =0;
taskTimer =0;
}
taskTimer++;
// 10 秒後離開這個狀態
if(taskTimer> 10*HZ_SETTING ){
stateCurrent = TASK_STATE_3;
}
}
void state3(){
/// 下面這區只有進來的時候會作一次 -------------------------------
if(stateCurrent!=stateLast){
/// 顯示一下目前的狀態
showStateName(stateCurrent);
/// 把狀態裡面的變數清空
stateLast =stateCurrent;
taskCounter =0;
taskTimer =0;
}
taskTimer++;
// 10 秒後離開這個狀態
if(taskTimer> 10*HZ_SETTING ){
stateCurrent = TASK_STATE_1;
}
}
void stateError(){
/// 下面這區只有進來的時候會作一次 -------------------------------
if(stateCurrent!=stateLast){
/// 顯示一下目前的狀態
showStateName(stateCurrent);
/// 把狀態裡面的變數清空
stateLast =stateCurrent;
taskCounter =0;
taskTimer =0;
}
taskTimer++;
// 10 秒 秀一下目前的狀態
if(( taskTimer % 10*HZ_SETTING )==0 ){
/// 顯示一下目前的狀態
showStateName(stateCurrent);
}
}
void stateUnknow(){
/// 下面這區只有進來的時候會作一次 -------------------------------
if(stateCurrent!=stateLast){
/// 顯示一下目前的狀態
showStateName(stateCurrent);
/// 把狀態裡面的變數清空
stateLast =stateCurrent;
taskCounter =0;
taskTimer =0;
}
taskTimer++;
// 10 秒 秀一下目前的狀態
if(( taskTimer % 10*HZ_SETTING )==0 ){
/// 顯示一下目前的狀態
showStateName(stateCurrent);
}
}
void doSM(){
switch(stateCurrent){
case TASK_STATE_INIT:
stateInit();
break;
case TASK_STATE_1:
state1();
break;
case TASK_STATE_2:
state2();
break;
case TASK_STATE_3:
state3();
break;
case TASK_STATE_ERROR:
stateError();
break;
default:
stateUnknow();
break;
}
}
void hw_init()
{
pinMode(LED_PIN, OUTPUT);
}
void process_command()
{
int aNumber, bNumber;
char *arg;
Serial.println("We're in process_command");
arg = SCmd.next();
if (arg != NULL)
{
aNumber = atoi(arg); // Converts a char string to an integer
Serial.print("First argument was: ");
Serial.println(aNumber);
}
else
{
Serial.println("No arguments");
aNumber = 999;
}
arg = SCmd.next();
if (arg != NULL)
{
bNumber = atol(arg);
Serial.print("Second argument was: ");
Serial.println(bNumber);
}
else
{
Serial.println("No second argument");
bNumber = 999;
}
switch (aNumber)
{
case 0:
Serial.print("stateCueent =");
Serial.println(stateCurrent);
break;
case 1:
//// 如果使用者沒有輸入參數,直接跳走
if(bNumber==999){
return;
}
stateCurrent = bNumber;
Serial.print("stateCueent =");
Serial.println(stateCurrent);
break;
case 2:
Serial.println("2");
break;
case 104:
Serial.println(VERSION);
break;
default:
break;
}
}
// This gets set as the default handler, and gets called when no other command matches.
void unrecognized()
{
Serial.println("What?");
}
void setup()
{
// put your setup code here, to run once:
Serial.begin(115200);
//Setup I/O
hw_init();
// register CMD
SCmd.addCommand("P", process_command); // Converts two arguments to integers and echos them back
SCmd.setDefaultHandler(unrecognized); // Handler for command that isn't matched (says "What?")
//setup WDT
wdt_enable(WDTO_4S);
}
void loop()
{
// put your main code here, to run repeatedly:
SCmd.readSerial(); // We don't do much, just
// 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();
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));
}
}