Using state machine for output colors and input from user

Hello,
I’m working on a project where I have the RGB led blink a series of 6 different colors. The user then has to recreate that series of colors, by pressing different buttons and the pressure sensor. I was unsure of how to allow for the user to respond to the color series, and someone on this forum suggested using a state machine. So, I’m trying it out, but I’m having some difficulty.

Here’s what’s happening:
I plug in the arduino, push the button to start the sequence. It plays a series of colors, but the series does not change every time the program starts. If I unplug the arduino and start the program again, the same series plays.
Next, I try to recreate the sequence. I push buttonLeft to initiate the user input portion of the program, and the led turns blue. Then, if I try to push other buttons, nothing else happens. If I push buttonLeft again right away, still nothing happens. I’m not sure what’s happening here.
After pushing a few more buttons, if I push buttonLeft again, it starts what appears to be a new sequence of colors. This sequence is different from the first sequence, but if I run the program again and get to this step again, the same sequence plays at this step.

I’m kind of lost, so any help will be appreciated. Should I get rid of all the other states, and just have one ‘output’ state and one ‘input’ state? Why is my ‘input’ portion not working?

Here is the code:

//==============SYSTEM STATES====
//INTIALIZE = 0
//PLAY = 1
//WAIT = 2
//USERINPUT = 3

int state = 0;  //master state

//========INITIALIZE PINS==========
int ledDigitalOne[] = {6,10,11};
//6 = red, 10 = green, 11= blue
int buttonRight = 4;
int buttonLeft = 8;
int pressureSense = 2;

//========DEFINE VARIABLES=========
const boolean ON=LOW;
const boolean OFF=HIGH;
int leftRead = HIGH;
int rightRead= HIGH;
int pressure = 0;
int correct = 0;


//========PREDEFINED COLORS=========
boolean GREEN[] = {OFF, ON, OFF};
boolean RED[] = {ON, OFF, OFF};
boolean BLUE[] = {OFF, OFF, ON};
boolean YELLOW[] = {ON,ON,OFF};
boolean CYAN[] = {OFF,ON,ON};
boolean MAGENTA[] = {ON,OFF,ON};

//======ARRAY TO STORE COLORS===========
const boolean* COLORS[] = {GREEN, RED, BLUE, YELLOW,CYAN,MAGENTA};

//INPUT AND OUTPUT ARRAYS
int randNum[6];
boolean* outputArray[6];
boolean* inputArray[6];





//==============SETUP===============
void setup()
{
   for(int i = 0;i<3; i++)
     pinMode(ledDigitalOne[i], OUTPUT); 
   pinMode(buttonRight, INPUT);
   pinMode(buttonLeft, INPUT);
     
}
  
//=====================LOOP==================  
void loop()
{

  
  switch(state)
  {
    case 0:  //INITIALIZE
      waitForPress();
      break;
    case 1:  //PLAY
      playOutputSequence();
      break;
    case 2:  //WAIT
      waitForStart();
      break;
    case 3:  //USERINPUT
      recordUserInput();
      break;
    
}
}

//=========================FUNCTIONS=================================
//sets led to color specified
void setColor(int* led, boolean* color)
{
  for(int i = 0; i<3;i++)
  {
    digitalWrite(led[i], color[i]);
  }
}
//==================================================
void waitForPress()
{
  leftRead = digitalRead(buttonLeft);
  if (leftRead ==LOW)
    state = 1;  //PLAY
}
//====================================================    
void playOutputSequence()
{
    //ASSIGN VALUES TO RANDNUM
  
  for (int i =0; i<6; i++)
  {
    randNum[i] = random(1, 1000);
  }
  
  //STORE COLORS IN OUTPUTARRAY
  
  for (int i = 0; i<6; i++)
  {
    if (randNum[i]>0 && randNum[i] <=167)
      outputArray[i] = GREEN;
    else if (randNum[i] >167 && randNum[i]<= 334)
       outputArray[i] = RED;
     else if (randNum[i] >334 && randNum[i]<= 501)
       outputArray[i] = BLUE;
     else if (randNum[i]>501 && randNum[i]<= 668)
       outputArray[i] = YELLOW;
     else if (randNum[i] >668 && randNum[i]<= 835)
       outputArray[i] = CYAN;
     else if (randNum[i] >835 && randNum[i]<= 1000)
       outputArray[i] = MAGENTA;
  }
  
  //SEND OUTPUT ARRAY TO SETCOLOR ONE AT A TIME
  for (int i=0;i<6;i++)
  {
    setColor(ledDigitalOne, outputArray[i]);
    delay(1000);
  }
  state = 2;    //WAIT
}
//======================================================   
void waitForStart()
{
  leftRead = digitalRead(buttonLeft);
  if (leftRead == LOW)
    state = 3;    //USERINPUT
   else;
}
//========================================
void recordUserInput()
{
pressure = analogRead(pressureSense);
leftRead = digitalRead(buttonLeft);
rightRead = digitalRead(buttonRight);
 //USER RESPONSE 
 for (int i= 0; i<6; i++)
{
  if (leftRead == LOW && rightRead ==LOW)
	inputArray[i] = GREEN;
  else if (rightRead ==LOW)
	inputArray[i] = RED;
  else if (leftRead ==LOW)
	inputArray[i] = BLUE;
  else if (rightRead == LOW && pressure >0)
	inputArray[i] = YELLOW;
  else if (leftRead == LOW && pressure>0)
	inputArray[i] = CYAN;
  else if (pressure>0 && leftRead == HIGH && rightRead == HIGH)
	inputArray[i] = MAGENTA;
  setColor(ledDigitalOne, inputArray[i]);
  delay(1000);
}

state = 0;   
}

I haven't got as far as working out your problem but I couldn't help noticing:

In your function playOutSequence. You generate six random numbers (between 1 and 999) and then go through all kinds of hoops to convert them to one of six colours. Wouldn't it be simpler to just pick one of these colours at random, six times?

Look up randomSeed in the reference page of this site.

Don't bother with random numbers until you get the rest of the program to work. It will be much easier to debug with a fixed set of colours.

...R

Okay, so I'll use a fixed set of colors to get the rest of the program to work for now.

KenF:
You generate six random numbers (between 1 and 999) and then go through all kinds of hoops to convert them to one of six colours. Wouldn't it be simpler to just pick one of these colours at random, six times?

So, don't use random numbers at all? This does sound simpler, but I'm not sure how to do what you're describing.

This does sound simpler, but I'm not sure how to do what you're describing.

Pick a random number between 1 and 6 (or 0 and 5) then there is no need to check the ranges between 0 and 999 to determine which colour has been chosen out of the 6 possible.

tghafo:
Okay, so I’ll use a fixed set of colors to get the rest of the program to work for now.So, don’t use random numbers at all? This does sound simpler, but I’m not sure how to do what you’re describing.

You want one of six colours to be chosen at random, yet you decide to get a value in the range of 0-999. And then go through so much pain to get it into the range that you want. This is what makes no sense to me.

This whole chunk

  for (int i =0; i<6; i++)
  {
    randNum[i] = random(1, 1000);
  }
  
  //STORE COLORS IN OUTPUTARRAY
  
  for (int i = 0; i<6; i++)
  {
    if (randNum[i]>0 && randNum[i] <=167)
      outputArray[i] = GREEN;
    else if (randNum[i] >167 && randNum[i]<= 334)
       outputArray[i] = RED;
     else if (randNum[i] >334 && randNum[i]<= 501)
       outputArray[i] = BLUE;
     else if (randNum[i]>501 && randNum[i]<= 668)
       outputArray[i] = YELLOW;
     else if (randNum[i] >668 && randNum[i]<= 835)
       outputArray[i] = CYAN;
     else if (randNum[i] >835 && randNum[i]<= 1000)
       outputArray[i] = MAGENTA;
  }

could be replaced with

for(int n=0;n<6;n++)
  outputArray[n]=(boolean*) COLORS[random(6)];

Oh okay, that makes sense for the outputArray. I guess I thought if I go 0-999 the series would be “more random”, but it was kind of unnecessary. I’m leaving the series fixed for now until I figure out the input part.

I’ve been trying to mess with the input portion, and I can’t figure out why it’s not working. I tell it state = 2, and to waitForStart(), and it does. However, when I press buttonRight to begin the input portion (I changed it, it was buttonLeft at first), the led turns red. Then, I try to push other buttons, and as before, the led does not change colors. Eventually, after pressing a few things, if I push buttonLeft again, the output colors start playing again. It seems to skip over recordUserInput().

Slightly updated code:

//==============SYSTEM STATES====
//INTIALIZE = 0
//PLAY = 1
//WAIT = 2
//USERINPUT = 3

int state = 0;  //master state

//========INITIALIZE PINS==========
int ledDigitalOne[] = {6,10,11};
//6 = red, 10 = green, 11= blue
int buttonRight = 4;
int buttonLeft = 8;
int pressureSense = 2;

//========DEFINE VARIABLES=========
const boolean ON=LOW;
const boolean OFF=HIGH;
int leftRead = HIGH;
int rightRead= HIGH;
int pressure = 0;
int correct = 0;


//========PREDEFINED COLORS=========
boolean GREEN[] = {OFF, ON, OFF};
boolean RED[] = {ON, OFF, OFF};
boolean BLUE[] = {OFF, OFF, ON};
boolean YELLOW[] = {ON,ON,OFF};
boolean CYAN[] = {OFF,ON,ON};
boolean MAGENTA[] = {ON,OFF,ON};

//======ARRAY TO STORE COLORS===========
const boolean* COLORS[] = {GREEN, RED, BLUE, YELLOW,CYAN,MAGENTA};

//INPUT AND OUTPUT ARRAYS
int randNum[6];
boolean* outputArray[6];
boolean* inputArray[6];





//==============SETUP===============
void setup()
{
   for(int i = 0;i<3; i++)
     pinMode(ledDigitalOne[i], OUTPUT); 
   pinMode(buttonRight, INPUT);
   pinMode(buttonLeft, INPUT);
     
}
  
//=====================LOOP==================  
void loop()
{

  
  switch(state)
  {
    case 0:  //INITIALIZE
      waitForPress();
      break;
    case 1:  //PLAY
      playOutputSequence();
      break;
    case 2:  //WAIT
      waitForStart();
      break;
    case 3:  //USERINPUT
      recordUserInput();
      break;
    
}
}

//=========================FUNCTIONS=================================
//sets led to color specified
void setColor(int* led, boolean* color)
{
  for(int i = 0; i<3;i++)
  {
    digitalWrite(led[i], color[i]);
  }
}
//==================================================
void waitForPress()
{
  leftRead = digitalRead(buttonLeft);
  if (leftRead ==LOW)
    state = 1;  //PLAY
}
//====================================================    
void playOutputSequence()
{
    //ASSIGN VALUES TO RANDNUM
  
  
  //make OUTPUTARRAY random
  for(int i=0;i<6;i++)
    outputArray[i] = (boolean*) COLORS[i];
    //outputArray[i]=(boolean*) COLORS[random(6)];
  
  //SEND OUTPUT ARRAY TO SETCOLOR ONE AT A TIME
  for (int i=0;i<6;i++)
  {
    setColor(ledDigitalOne, outputArray[i]);
    delay(1000);
  }
  state = 2;    //WAIT
}
//======================================================   
void waitForStart()
{
  rightRead = digitalRead(buttonRight);
  if (rightRead ==LOW)
    state = 3;    //USERINPUT
   else;
}
//========================================
void recordUserInput()
{
pressure = analogRead(pressureSense);
leftRead = digitalRead(buttonLeft);
rightRead = digitalRead(buttonRight);
 //USER RESPONSE 
 for (int i= 0; i<6; i++)
{
  if (leftRead == LOW && rightRead ==LOW)
	inputArray[i] = GREEN;
  else if (rightRead ==LOW)
	inputArray[i] = RED;
  else if (leftRead ==LOW)
	inputArray[i] = BLUE;
  else if (rightRead == LOW && pressure >0)
	inputArray[i] = YELLOW;
  else if (leftRead == LOW && pressure>0)
	inputArray[i] = CYAN;
  else if (pressure>0 && leftRead == HIGH && rightRead == HIGH)
	inputArray[i] = MAGENTA;
  setColor(ledDigitalOne, inputArray[i]);
  delay(1000);
}

state = 0;   
}