Adafruit_RGB_LCD SHIELD FINITE STATE MACHINE PROJ

here's a simple state machine from another thread

#undef MyHW
#ifdef MyHW
const byte pinCutL   = A1;
const byte pinCutR   = A2;
const byte pinHandL  = A3;
const byte pinHandR  = A4;

const byte pinAdvA   = 10;
const byte pinAdvB   = 11;
const byte pinCutA   = 12;
const byte pinCutB   = 13;
const byte pinAdvSpd = 8;
const byte pinCutSpd = 9;

#else
const byte pinCutL   = 1;
const byte pinCutR   = 2;
const byte pinHandL  = 3;
const byte pinHandR  = 4;

const byte pinAdvA   = 5;
const byte pinAdvB   = 6;
const byte pinCutA   = 7;
const byte pinCutB   = 8;
const byte pinAdvSpd = 9;
const byte pinCutSpd = 10;
#endif


const byte pinsInp [] = { pinCutL, pinCutR, pinHandL, pinHandR };
const byte pinsOut [] = { pinAdvA, pinAdvB, pinCutA,
                          pinCutB, pinAdvSpd, pinCutSpd };

#define N_INP   sizeof (pinsInp)
#define N_OUT   sizeof (pinsOut)

enum { ST_IDLE, ST_ADV, ST_CUT };
int state = ST_IDLE;


// -----------------------------------------------------------------------------
void
motorForward (
    byte pinA,
    byte pinB )
{
    digitalWrite (pinA, HIGH);
    digitalWrite (pinB, LOW);
}

// -------------------------------------
void
motorReverse (
    byte pinA,
    byte pinB )
{
    digitalWrite (pinA, LOW);
    digitalWrite (pinB, HIGH);
}

// -------------------------------------
void
motorStop (
    byte pinA,
    byte pinB )
{
    digitalWrite (pinA, LOW);
    digitalWrite (pinB, LOW);
}

// -----------------------------------------------------------------------------
byte pinCutStop;

void
cutterStart (void)
{
    if (LOW == digitalRead (pinCutL))  {
        motorForward (pinCutA, pinCutB);
        pinCutStop = pinCutR;
    }
    else  {
        motorReverse (pinCutA, pinCutB);
        pinCutStop = pinCutL;
    }
}

// -------------------------------------
int
cutterMonitor (void)
{
    if (LOW == digitalRead (pinCutStop))  {
        motorStop (pinCutA, pinCutB);
        return 1;
    }

    return 0;
}

// -----------------------------------------------------------------------------
void
loop ()
{
    switch (state)  {
    case ST_IDLE:
        if (digitalRead (pinHandL) == LOW || digitalRead (pinHandR) == LOW) {
            motorForward (pinAdvA, pinAdvB);
            state = ST_ADV;
        }
        break;

    case ST_ADV:
        if (digitalRead (pinHandL) == HIGH && digitalRead (pinHandR) == HIGH) {
            motorStop (pinAdvA, pinAdvB);
            cutterStart ();
            state = ST_CUT;
        }
        break;

    case ST_CUT:
        if (cutterMonitor ())
            state = ST_IDLE;
        break;
    }
}

// -----------------------------------------------------------------------------
void setup ()
{
    for (unsigned n = 0; n < N_INP; n++)
        pinMode (pinsInp [n], INPUT_PULLUP);

    for (unsigned n = 0; n < N_OUT; n++)  {
        digitalWrite (pinsOut [n], LOW);
        pinMode (pinsOut [n], OUTPUT);
    }

    //control motor speed
    analogWrite (pinAdvSpd, 255);
    analogWrite (pinCutSpd, 255);

}
1 Like

personally I think it is not a good idea to rely on the order of enum entries nor to give the enum elements a specific value. IMHO a state machine should describe what is the next step when a specific event in a specific state occures.

When you google how to iterate over an enum you might find some ideas.
Even if downvoted by others I find this option the least worst one, easy to follow and working for the Arduino / C++11: the overload of the ++ operator:
https://stackoverflow.com/questions/261963/how-can-i-iterate-over-an-enum/58983366#58983366

I've implemented a Proof of Concept in my Sketch from post #11 and it seems to compile and work

enum class State { FIXTEXT, RUNTIME, RANDOM} state;      // what kind of data should be shown
//based on https://stackoverflow.com/questions/261963/how-can-i-iterate-over-an-enum/58983366#58983366
State& operator++(State &c, int)
{
  switch (c)
  {
    case State::FIXTEXT:
      return c = State::RUNTIME;
    case State::RUNTIME:
      return c = State::RANDOM;
    case State::RANDOM:
      return c = State::FIXTEXT; // managing overflow
  }
  return c;                      // avoid warning
}

this gives you a ++ operator for the state:

        //state = State::RUNTIME;  // replaced testwise
        state++; // testwise
2 Likes

my biggest fear of trying to do something with this is its not using the millis() and therefore i am extremely fearful noiasica's machine would not react to real time.

Noiasca should i implement your proof of concept

 //  State& operator++(State &c, int) 

inside or outside of the runFSM method and why?

the overload of the ++ operator can be defined like any other function.
So I've kept it directly after the enum definition to make it clear, that there is a ++ operator for state, and if someone adds new states to the enum, he must also adopt the ++ operator.

In the runFSM() you just use state++;

I basically gave up after a few hours because I don't understand how to achieve what I want

Is there anyone willing to tutor me to help me or i guess help me with noiasca's program for cheap? I am willing to pay a little, again its a hobby proj. if not i guess is what it is.