Arduino Game Board - Q/A

See if you can follow this:

//********************************************************************************************************
// Version   YY/MM/DD   Description
// 1.00      21 11 20   working sketch 
//
//Matching a question to the correct answer turns on the "Correct Green LED"
//Matching a question to the wrong answer turns on the "Wrong Red LED"
//
//********************************************************************************************************


#define PUSHED                 HIGH

const byte GreenledPin13     = 13;  //Correct Answer LED
const byte RedledPin12       = 12;  //Wrong Answer LED

const byte greenbuttonPin2   = 2;   //first push button
const byte greenbuttonPin3   = 3;   //second push button

const byte orangebuttonPin4  = 4;   //first push button
const byte orangebuttonPin5  = 5;   //second push button

const byte redbuttonPin6     = 6;   //first push button
const byte redbuttonPin7     = 7;   //second push button

byte oldPin2State            = !PUSHED;
byte oldPin3State            = !PUSHED;

byte oldPin4State            = !PUSHED;
byte oldPin5State            = !PUSHED;

byte oldPin6State            = !PUSHED;
byte oldPin7State            = !PUSHED;

byte state;
byte Flag                    = 0b00000000;

unsigned long switchMillis;


//********************************************************************************************************
void setup()
{
  Serial.begin(9600);

  pinMode(GreenledPin13, OUTPUT);
  pinMode(RedledPin12, OUTPUT);

  pinMode(greenbuttonPin2, INPUT_PULLUP);
  pinMode(greenbuttonPin3, INPUT_PULLUP);

  pinMode(orangebuttonPin4, INPUT_PULLUP);
  pinMode(orangebuttonPin5, INPUT_PULLUP);

  pinMode(redbuttonPin6, INPUT_PULLUP);
  pinMode(redbuttonPin7, INPUT_PULLUP);

} //END of setup()


//********************************************************************************************************
void loop()
{
  //******************************************
  //is it time to check the switches ?
  if (millis() - switchMillis >= 50)
  {
    //restart the TIMER
    switchMillis = millis();

    checkSwitches();
  }

  //******************************************
  //right answer
  if (Flag == 3 || Flag == 12 || Flag == 48)
  {
    //Green LED ON
    digitalWrite(GreenledPin13, HIGH);
  }
  else
  {
    //Green LED OFF
    digitalWrite(GreenledPin13, LOW);
  }

  //******************************************
  //wrong answer
  if (Flag == 9 || Flag == 33 || Flag == 6 || Flag == 36 || Flag == 18 || Flag == 24)
  {
    //Red LED ON
    digitalWrite(RedledPin12, HIGH);
  }
  else
  {
    //Red LED OFF
    digitalWrite(RedledPin12, LOW);
  }

} //END of loop()


//********************************************************************************************************
void checkSwitches()
{
  //**************************************************************** G r e e n
  //Question
  state = digitalRead(greenbuttonPin2);

  //was there a change in switch state ?
  if (oldPin2State != state)
  {
    //update to the new state
    oldPin2State = state;
  }

  //was the switch PUSHED ?
  if (state == PUSHED)
  {
    Flag = Flag | 0b00000001;
  }

  else
  {
    Flag = Flag & 0b11111110;
  }

  //***********************************
  //Answer
  state = digitalRead(greenbuttonPin3);

  //was there a change in switch state ?
  if (oldPin3State != state)
  {
    //update to the new state
    oldPin3State = state;
  }

  //was the switch PUSHED ?
  if (state == PUSHED)
  {
    Flag = Flag | 0b00000010;
  }

  else
  {
    Flag = Flag & 0b11111101;
  }

  //**************************************************************** O r a n g e
  //Question
  state = digitalRead(orangebuttonPin4);

  //was there a change in switch state ?
  if (oldPin4State != state)
  {
    //update to the new state
    oldPin4State = state;
  }

  //was the switch PUSHED ?
  if (state == PUSHED)
  {
    Flag = Flag | 0b00000100;
  }

  else
  {
    Flag = Flag & 0b11111011;
  }

  //***********************************
  //Answer
  state = digitalRead(orangebuttonPin5);

  //was there a change in switch state ?
  if (oldPin5State != state)
  {
    //update to the new state
    oldPin5State = state;
  }

  //was the switch PUSHED ?
  if (state == PUSHED)
  {
    Flag = Flag | 0b00001000;
  }

  else
  {
    Flag = Flag & 0b11110111;
  }

  //**************************************************************** R E D
  //Question
  state = digitalRead(redbuttonPin6);

  //was there a change in switch state ?
  if (oldPin6State != state)
  {
    //update to the new state
    oldPin6State = state;
  }

  //was the switch PUSHED ?
  if (state == PUSHED)
  {
    Flag = Flag | 0b00010000;
  }

  else
  {
    Flag = Flag & 0b11101111;
  }

  //***********************************
  //Answer
  state = digitalRead(redbuttonPin7);

  //was there a change in switch state ?
  if (oldPin7State != state)
  {
    //update to the new state
    oldPin7State = state;
  }

  //was the switch PUSHED ?
  if (state == PUSHED)
  {
    Flag = Flag | 0b00100000;
  }

  else
  {
    Flag = Flag & 0b11011111;
  }

  //***********************************

  Serial.println(Flag);

} //END of checkSwitches()

1 Like

Thank you! Exactly what I want and yes would want both buttons pushed at the same time. I'll read up on State machines.

This will take me some time. I did upload it and get a solid green light steady all the time. Press of any 1 button turns it off while pressing button. As soon as my finger comes off the button it lights back up.

I had an early mistake in the sketch.

Make sure you are using the current posted sketch.

i.e.
This is the correction if your switches are wired to give a HIGH on a push:
#define PUSHED HIGH


My switches are wired to give a LOW on a push so I needed:
#define PUSHED LOW


1 Like

Finally I can post! The forum locked me down on posting for the day. A timer started after my last post counting down.
Very nice solution!!! And it is almost perfect. Each pair works perfectly to light up the Green LED!
Pressing the wrong pair does light up the Red LED, however not on both buttons. Example:
Red Button #2 + Orange Button #1 = Red Light
Red Button #2 + Green Button #1 = Red Light
Red Button #2 + Orange Button #2 = No Red Light
Red Button #2 + Green Button #2 = No Red Light
& Vice Versa if you started with the #1 button.

Are you not supposed to press a Question button then an Answer button ?

If understand you correctly, you want the Red answer button and the Green answer button to turn on the Red LED ? If so why ?

Please explain a bit more ?

1 Like

You are totally correct! I got myself confused.
OK - I need to have a total of 12 Questions. How do I go about adding the additional right and wrong answer flags? It looks like the was switch pushed flag increments by x 10 but i'm lost with the else flag.

  • Changes need to go form 3 to 12 switches, see the Structure QandA
  • To be tested.
//https://forum.arduino.cc/t/arduino-game-board-q-a/927329

//*********************************************************************************
// Version   YY/MM/DD   Description
// 1.00      21 11 20   working sketch
// 1.02      21 11 20   Added a Structure definition so we can easily have 12 QandAs
// 1.03      21 11 20   needs additions and testing for 12 switches
//
//Matching a question to the correct answer turns on the "Correct Green LED"
//Matching a question to the wrong answer turns on the "Wrong Red LED"
//
//*********************************************************************************

#define PUSHED                    HIGH      //switch closed gives a HIGH on the pin

#define LEDon                     HIGH
#define LEDoff                    LOW

const byte GreenledPin13        = 13;       //Correct Answer LED
const byte RedledPin12          = 12;       //Wrong Answer LED

byte RedLEDflag;
byte GreenLEDFlag;

//******************************************
//define the Question and Answer Structure
struct QandA
{
  const byte    Qpin;
  const byte    Apin;
  byte          bitNumQ;
  byte          bitNumA;
  byte          lastStateQ;
  byte          lastStateA;
}; //END of structure QandA

const byte numQuestions         = 3;

QandA pairNum[numQuestions]     =
{
  { 2,  3, 0, 1, !PUSHED, !PUSHED},    //pair #1  Qpin Apin bitNumQ bitNumA lastStateQ lastStateA
  { 4,  5, 2, 3, !PUSHED, !PUSHED},    //pair #2
  { 6,  7, 4, 5, !PUSHED, !PUSHED},    //pair #3
  //{ 8,  9, 6, 7, !PUSHED, !PUSHED},    //pair #4  <----<<<<  add the other switches in the game
  //{10, 11, 8, 9, !PUSHED, !PUSHED},    //pair #5   
  //etc.
};
//
//END of our Structure and definition
//******************************************

byte state;

//The flag is 32 bits, corresponds to 16 question/answer pairs
//A=Answer, Q=Question           AQAQAQAQAQAQAQAQAQAQAQAQAQAQAQAQ
//                               11111111111111
//                               66554433221100998877665544332211
//                               --------------------------------
//Bit                            3022222222221111111111
//Number                         10987654321098765432109876543210
unsigned long Flag           = 0b00000000000000000000000000000000;  //32 bits

//answer switch pushed
unsigned long answer[12]     = {2, 8, 32, 128, 512, 2048, 8192, 32768, 131072, 524288, 2097152, 8388608};

//question switch pushed
unsigned long question[12]   = {1, 4, 16, 64, 256, 1024, 4096, 16384, 65536, 262144, 1048576, 4194304};

//timing stuff
unsigned long switchMillis;


//*********************************************************************************
void setup()
{
  Serial.begin(9600);

  pinMode(GreenledPin13, OUTPUT);
  pinMode(RedledPin12, OUTPUT);

  for (byte x = 0; x < numQuestions; x++)
  {
    pinMode(pairNum[x].Qpin, INPUT_PULLUP);
    pinMode(pairNum[x].Apin, INPUT_PULLUP);
  }

} //END of setup()


//*********************************************************************************
void loop()
{
  //******************************************
  //is it time to check the switches ?
  if (millis() - switchMillis >= 50)
  {
    //restart the TIMER
    switchMillis = millis();

    checkSwitches();
  }

  //******************************************
  //operate LEDs as per switches pushed
  //initialize
  RedLEDflag = LEDon;

  //no switches are pushed ?
  if (Flag == 0)
  {
    GreenLEDFlag = LEDoff;
    RedLEDflag = LEDoff;
  }

  //correct question and answered switches are pushed ?
  for (byte x = 0; x < 12; x++)
  {
    if (Flag == question[x] + answer[x])
    {
      GreenLEDFlag = LEDon;
      RedLEDflag = LEDoff;
    }
  }

  //a question switch is pushed ?
  for (byte x = 0; x < 12; x++)
  {
    if (Flag == question[x])
    {
      GreenLEDFlag = LEDoff;
      RedLEDflag = LEDoff;
    }
  }

  //an answer switch is pushed ?
  for (byte x = 0; x < 12; x++)
  {
    if (Flag == answer[x])
    {
      GreenLEDFlag = LEDoff;
      RedLEDflag = LEDoff;
    }
  }

  //update the LEDs
  digitalWrite(GreenledPin13, GreenLEDFlag);
  digitalWrite(RedledPin12, RedLEDflag);

  //******************************************

} //END of loop()


//*********************************************************************************
void checkSwitches()
{
  //scan all the switches to see if there are changes in state, act accordingly
  for (byte x = 0; x < numQuestions; x++)
  {
    //***************************************
    //current Question
    state = digitalRead(pairNum[x].Qpin);

    //was there a change in state ?
    if (pairNum[x].lastStateQ != state)
    {
      //update to the new state
      pairNum[x].lastStateQ = state;
    }
    //was the switch PUSHED ?
    if (state == PUSHED)
    {
      //set the flag bit
      Flag = Flag | bit(pairNum[x].bitNumQ);
    }

    else
    {
      //reset the flag bit
      Flag = Flag & ~bit(pairNum[x].bitNumQ);
    }

    //***************************************
    //current Answer
    state = digitalRead(pairNum[x].Apin);

    //was there a change in state ?
    if (pairNum[x].lastStateA != state)
    {
      //update to the new state
      pairNum[x].lastStateA = state;
    }
    //was the switch PUSHED ?
    if (state == PUSHED)
    {
      //set the flag bit
      Flag = Flag | bit(pairNum[x].bitNumA);
    }

    else
    {
      //reset the flag bit
      Flag = Flag & ~bit(pairNum[x].bitNumA);
    }
  }

  //***********************************
  //print the Flag so we can see the switch pushed total
  Serial.println(Flag);

} //END of checkSwitches()

//*********************************************************************************
1 Like

Your awesome! Added another button and it worked great! Will add all of my other buttons and get back to you on final testing. Thanks again Larry!

Highly recommend you wire your switches as I wired mine.

See the schematic provided above, post #24.

This way you do not need the twenty four pull down resistors !

1 Like

Now your talking! Will do that for sure. Thanks for that. Then just change back:
#define PUSHED LOW instead of HIGH?

Yes

1 Like

1 Like

I continued on with Pins 10,11
and then jumped to 23,24 but am not sure if I just keep counting up?

const byte numQuestions         = 10;

QandA pairNum[numQuestions]     =
{
  { 2,  3, 0, 1, !PUSHED, !PUSHED},    //pair #1  Qpin Apin bitNumQ bitNumA lastStateQ lastStateA
  { 4,  5, 2, 3, !PUSHED, !PUSHED},    //pair #2
  { 6,  7, 4, 5, !PUSHED, !PUSHED},    //pair #3
  { 8,  9, 6, 7, !PUSHED, !PUSHED},    //pair #4  <----<<<<  add the other switches in the game
  {10, 11, 8, 9, !PUSHED, !PUSHED},    //pair #5   
  **{23, 24, 10, 11, !PUSHED, !PUSHED},    //pair #6**   
  {25, 26, 12, 13, !PUSHED, !PUSHED},    //pair #7
  {27, 28, 14, 15, !PUSHED, !PUSHED},    //pair #8
  {29, 30, 16, 17, !PUSHED, !PUSHED},    //pair #9
  {31, 32, 18, 19, !PUSHED, !PUSHED},    //pair #10  
  
  //etc.

You can use what ever pin combinations you want, however, if you follow the schematic below you get the following sketch.

Note the LEDs are now on the pins shown in the schematic.

//
// https://forum.arduino.cc/t/arduino-game-board-q-a/927329
//
//*********************************************************************************
// Version   YY/MM/DD   Description
// =======   ========   ===========
// 1.00      21 11 20   Working sketch
// 1.02      21 11 20   Added a Structure definition so we can easily have 12 QandAs
// 1.03      21 11 20   Needs additions and testing for 12 switches
// 1.04      21 11 21   Combined some tests; added some comments
// 1.05      21 11 21   Added trapping for more than 2 switches pressed; added heartbeat LED and buzzer
// 1.06      21 11 21   Move the switches to different controller pins
//
// Matching a question to the correct answer turns on the "Correct Green LED"
// Matching a question to the wrong answer turns on the "Wrong Red LED"
//
//*********************************************************************************

//5V---[Internal 50k Resistor]---Pin---[Switch]---GND
#define PUSHED                    LOW

//Pin---[220R]---[A->|-K]---GND
#define LEDon                     HIGH
#define LEDoff                    LOW

#define ENABLED                   true
#define DISABLED                  false

//******************************************

//const byte buzzer               = 15;
//const byte heartbeatLED         = 14;
//const byte GreenLED             = 13;       //Correct Answer LED
//const byte RedLED               = 12;       //Wrong Answer LED

const byte buzzer               = 50;
const byte heartbeatLED         = 51;
const byte GreenLED             = 52;       //Correct Answer LED
const byte RedLED               = 53;       //Wrong Answer LED

byte RedLEDflag;
byte GreenLEDFlag;
byte switchCount;

//******************************************
//define the Question and Answer Structure
struct QandA
{
  const byte Qpin;
  const byte Apin;
  byte       bitNumQ;
  byte       bitNumA;
  byte       lastStateQ;
  byte       lastStateA;

}; //END of struct QandA

//******************************************
//the number of QandA pairs to be defined
const byte numQuestions         = 12;

//define all the objects
QandA pairNum[numQuestions]     =
{
  // pins    bits   last Q   last A
  //Q   A   Q   A
  //======  ====== ======== ========
  { 2,  3,  0,  1, !PUSHED, !PUSHED},    //pair #1     Qpin Apin bitNumQ bitNumA lastStateQ lastStateA
  { 4,  5,  2,  3, !PUSHED, !PUSHED},    //pair #2
  { 6,  7,  4,  5, !PUSHED, !PUSHED},    //pair #3
  {22, 23,  6,  7, !PUSHED, !PUSHED},    //pair #4
  {24, 25,  8,  9, !PUSHED, !PUSHED},    //pair #5
  {26, 27, 10, 11, !PUSHED, !PUSHED},    //pair #6
  {28, 29, 12, 13, !PUSHED, !PUSHED},    //pair #7
  {30, 31, 14, 15, !PUSHED, !PUSHED},    //pair #8
  {32, 33, 16, 17, !PUSHED, !PUSHED},    //pair #9
  {34, 35, 18, 19, !PUSHED, !PUSHED},    //pair #10
  {36, 37, 20, 21, !PUSHED, !PUSHED},    //pair #11
  {38, 39, 22, 23, !PUSHED, !PUSHED}     //pair #12
};

//
//END of our Structure and definition
//******************************************

byte state;

//The flag is 32 bits, corresponds to 16 question/answer pairs
//A=Answer, Q=Question           AQAQAQAQAQAQAQAQAQAQAQAQAQAQAQAQ
//Q and A number                 11111111111111
//                               66554433221100998877665544332211
//                               --------------------------------
//Bit                            3322222222221111111111
//Number                         10987654321098765432109876543210
unsigned long Flag           = 0b00000000000000000000000000000000;  //32 bits

//question switch pushed
unsigned long question[12]   = {1, 4, 16, 64,  256, 1024, 4096, 16384,  65536, 262144, 1048576, 4194304};
//element #                     0  1   2   3     4     5     6      7       8       9       10       11

//answer switch pushed
unsigned long answer[12]     = {2, 8, 32, 128, 512, 2048, 8192, 32768, 131072, 524288, 2097152, 8388608};
//element #                     0  1   2    3    4     5     6      7       8       9       10       11

//timing stuff
unsigned long switchMillis;
unsigned long heartbeatMillis;

//*********************************************************************************
void setup()
{
  Serial.begin(9600);

  pinMode(buzzer, OUTPUT);
  pinMode(heartbeatLED, OUTPUT);
  pinMode(GreenLED, OUTPUT);
  pinMode(RedLED, OUTPUT);

  for (byte x = 0; x < numQuestions; x++)
  {
    pinMode(pairNum[x].Qpin, INPUT_PULLUP);
    pinMode(pairNum[x].Apin, INPUT_PULLUP);
  }

} //END of setup()


//*********************************************************************************
void loop()
{
  //***************************************
  //time to toggle the heartbeat LED ?
  if (millis() - heartbeatMillis >= 500)
  {
    //restart the TIMER
    heartbeatMillis = millis();

    //toggle LED
    digitalWrite(heartbeatLED, !digitalRead(heartbeatLED));

  }

  //******************************************
  //is it time to check the switches ?
  if (millis() - switchMillis >= 50)
  {
    //restart the TIMER
    switchMillis = millis();

    checkSwitches();
  }

  //******************************************
  //control the LEDs as per switches pushed
  //
  //initialize
  RedLEDflag = LEDon;

  //more than 2 switches pressed ?
  if (switchCount > 2)
  {
    GreenLEDFlag = LEDoff;
  }

  //no switches are pushed ?
  else if (Flag == 0)
  {
    GreenLEDFlag = LEDoff;
    RedLEDflag = LEDoff;
  }

  else
  {
    //check what switches are being pushed
    for (byte x = 0; x < 12; x++)
    {
      //************************
      //the correct switches are pushed ?
      if (Flag == question[x] + answer[x])
      {
        GreenLEDFlag = LEDon;
        RedLEDflag = LEDoff;

        //we found them, no need to go further
        break;
      }

      //************************
      //1 question switch is pushed ?
      else if (Flag == question[x])
      {
        GreenLEDFlag = LEDoff;
        RedLEDflag = LEDoff;

        //we found it, no need to go further
        break;
      }

      //************************
      //1 answer switch is pushed ?
      else if (Flag == answer[x])
      {
        GreenLEDFlag = LEDoff;
        RedLEDflag = LEDoff;

        //we found it, no need to go further
        break;
      }

    } //END of for (byte x = 0; x < 12; x++)

  } //END of else()

  //******************************************
  //update the LEDs and sound the buzzer as needed
  digitalWrite(GreenLED, GreenLEDFlag);
  digitalWrite(RedLED, RedLEDflag);

  //************************
  if (GreenLEDFlag == LEDon)
  {
    tone(buzzer, 4000, 500);
  }

  if (RedLEDflag == LEDon)
  {
    tone(buzzer, 500, 500);
  }

  //******************************************

} //END of loop()


//*********************************************************************************
void checkSwitches()
{
  //scan all the switches to see if there are changes in state, act accordingly
  for (byte x = 0; x < numQuestions; x++)
  {
    //***************************************
    //current Question
    state = digitalRead(pairNum[x].Qpin);

    //was there a change in state ?
    if (pairNum[x].lastStateQ != state)
    {
      //update to the new state
      pairNum[x].lastStateQ = state;

      //******************
      //was the switch PUSHED ?
      if (state == PUSHED)
      {
        switchCount++;

        //set the flag bit
        Flag = Flag | bit(pairNum[x].bitNumQ);
      }

      //******************
      //the switch was released
      else
      {
        switchCount--;

        //reset the flag bit
        Flag = Flag & ~bit(pairNum[x].bitNumQ);
      }

      //******************
      //print the Flag so we can see the total
      Serial.print(Flag);

      //print the number of switches being pressed
      Serial.print("\t Switches pressed = ");
      Serial.println(switchCount);

    } //END of  if (pairNum[x].lastStateQ != state)

    //***************************************
    //current Answer
    state = digitalRead(pairNum[x].Apin);

    //******************
    //was there a change in state ?
    if (pairNum[x].lastStateA != state)
    {
      //update to the new state
      pairNum[x].lastStateA = state;

      //was the switch PUSHED ?
      if (state == PUSHED)
      {
        switchCount++;

        //set the flag bit
        Flag = Flag | bit(pairNum[x].bitNumA);
      }

      //******************
      //the switch was released
      else
      {
        switchCount--;

        //reset the flag bit
        Flag = Flag & ~bit(pairNum[x].bitNumA);
      }

      //******************
      //print the Flag so we can see the total
      Serial.print(Flag);

      //print the number of switches being pressed
      Serial.print("\t Switches pressed = ");
      Serial.println(switchCount);

    } //END of  if (pairNum[x].lastStateA != state)

  } //END of  for (byte x = 0; x < numQuestions; x++)

}//END of checkSwitches()

//*********************************************************************************
1 Like

Thanks Larry! Got it all wired up but must have a wiring issue. Will let you know how it goes.

You do know you have to show us the finished product ? :wink:

1 Like

Hope you had a great Thanksgiving! Just wired it up. Works great! Purchased these right and wrong answer buzzers. My son realized you could get correct and incorrect buzzer sounds out of the same buzzer based on wiring. So we have one buzzer that does both sounds which is nice.
Amazon.com : Right & Wrong Answer Buzzers (2 pcs) New & Improved : Toys & Games


Uploading: IMG_2041.jpg...

Same to you.



Looking good!

Nice to see you are having fun with your son.

Have a great holiday season !


Highly suggest you look into making your own Dupont cables.

Making DuPont jumper wires.pdf (1.24 MB)


Attached is an updated sketch, a few small changes:

//
// https://forum.arduino.cc/t/arduino-game-board-q-a/927329
//
//*********************************************************************************
// Version   YY/MM/DD   Description
// =======   ========   ===========
// 1.00      21 11 20   Working sketch
// 1.02      21 11 20   Added a Structure definition so we can easily have 12 QandAs
// 1.03      21 11 20   Needs additions and testing for 12 switches
// 1.04      21 11 21   Combined some tests; added some comments
// 1.05      21 11 21   Added trapping for more than 2 switches pressed;
//                      added heartbeat LED and buzzer
// 1.06      21 11 21   Move the switches to different controller pins
// 1.07      21 11 27   To speed up execution time, added switchChangeFlag
//
// Matching a question to the correct answer turns on the "Correct Green LED"
// Matching a question to the wrong answer turns on the "Wrong Red LED"
//

//*********************************************************************************

//if the next line is commented, NO debug code is generated
//#define DEBUG  

#ifdef DEBUG
//                                for oscilloscope triggering
#define PULSE9                    cli(); PINB = bit(PINB1); PINB = bit(PINB1); sei()

#else
#define PULSE9                    //nothing defined

#endif

//*********************************************************************************

//5V---[Internal 50k Resistor]---Pin---[Switch]---GND
#define PUSHED                    LOW

//Pin---[220R]---[A->|-K]---GND
#define LEDon                     HIGH
#define LEDoff                    LOW

#define ENABLED                   true
#define DISABLED                  false

//******************************************


//const byte buzzer               = 12;
//const byte heartbeatLED         = 13;
//const byte GreenLED             = 11;       //Correct Answer LED
//const byte RedLED               = 10;       //Wrong Answer LED

#ifdef DEBUG
const byte pulsePin               = 9;      //pin PINB1, for oscilloscope triggering
#endif

const byte buzzer               = 50;
const byte heartbeatLED         = 51;
const byte GreenLED             = 52;       //Correct Answer LED
const byte RedLED               = 53;       //Wrong Answer LED

bool switchChangeFlag             = DISABLED;

byte RedLEDflag;
byte GreenLEDFlag;
byte switchCount;

//******************************************
//define the Question and Answer Structure
struct QandA
{
  const byte Qpin;
  const byte Apin;
  byte       bitNumQ;
  byte       bitNumA;
  byte       lastStateQ;
  byte       lastStateA;

}; //END of struct QandA

//******************************************
//the number of QandA pairs to be defined
const byte numQuestions         = 12;

//define all the objects
QandA pairNum[numQuestions]     =
{
  // pins    bits   last Q   last A
  //Q   A   Q   A
  //======  ====== ======== ========
  { 2,  3,  0,  1, !PUSHED, !PUSHED},    //pair #1     Qpin Apin bitNumQ bitNumA lastStateQ lastStateA
  { 4,  5,  2,  3, !PUSHED, !PUSHED},    //pair #2
  { 6,  7,  4,  5, !PUSHED, !PUSHED},    //pair #3
  {22, 23,  6,  7, !PUSHED, !PUSHED},    //pair #4
  {24, 25,  8,  9, !PUSHED, !PUSHED},    //pair #5
  {26, 27, 10, 11, !PUSHED, !PUSHED},    //pair #6
  {28, 29, 12, 13, !PUSHED, !PUSHED},    //pair #7
  {30, 31, 14, 15, !PUSHED, !PUSHED},    //pair #8
  {32, 33, 16, 17, !PUSHED, !PUSHED},    //pair #9
  {34, 35, 18, 19, !PUSHED, !PUSHED},    //pair #10
  {36, 37, 20, 21, !PUSHED, !PUSHED},    //pair #11
  {38, 39, 22, 23, !PUSHED, !PUSHED}     //pair #12
};

//
//END of our Structure and definition
//******************************************

byte currentState;

//The flag is 32 bits, corresponds to 16 question/answer pairs
//A=Answer, Q=Question           AQAQAQAQAQAQAQAQAQAQAQAQAQAQAQAQ
//Q and A number                 11111111111111
//                               66554433221100998877665544332211
//                               --------------------------------
//Bit                            3322222222221111111111
//Number                         10987654321098765432109876543210
unsigned long Flag           = 0b00000000000000000000000000000000;  //32 bits

//question switch pushed
unsigned long question[12]   = {1, 4, 16, 64,  256, 1024, 4096, 16384,  65536, 262144, 1048576, 4194304};
//element #                     0  1   2   3     4     5     6      7       8       9       10       11

//answer switch pushed
unsigned long answer[12]     = {2, 8, 32, 128, 512, 2048, 8192, 32768, 131072, 524288, 2097152, 8388608};
//element #                     0  1   2    3    4     5     6      7       8       9       10       11

//timing stuff
unsigned long switchMillis;
unsigned long heartbeatMillis;

//*********************************************************************************
void setup()
{
  Serial.begin(9600);

  pinMode(buzzer, OUTPUT);
  pinMode(heartbeatLED, OUTPUT);
  pinMode(GreenLED, OUTPUT);
  pinMode(RedLED, OUTPUT);

#ifdef DEBUG
  pinMode(pulsePin , OUTPUT);
  digitalWrite(pulsePin, LOW);
#endif

  //***************************************
  for (byte x = 0; x < numQuestions; x++)
  {
    pinMode(pairNum[x].Qpin, INPUT_PULLUP);
    pinMode(pairNum[x].Apin, INPUT_PULLUP);
  }

} //END of setup()


//*********************************************************************************
void loop()
{
  //***************************************
  //time to toggle the heartbeat LED ?
  if (millis() - heartbeatMillis >= 500)
  {
    //restart the TIMER
    heartbeatMillis = millis();

    //toggle LED
    digitalWrite(heartbeatLED, !digitalRead(heartbeatLED));

  }

  //******************************************
  //is it time to check the switches ?
  if (millis() - switchMillis >= 50)
  {
    //restart the TIMER
    switchMillis = millis();

    checkSwitches();

  }

  //******************************************
  //has there been a state change in any of the switches ?
  if (switchChangeFlag == ENABLED)
  {
    //yes, okay, we will deal with it
    switchChangeFlag = DISABLED;

    controlLEDs();
  }

  //******************************************
  //other none blocking code goes here
  //******************************************

} //END of loop()


//*********************************************************************************
void controlLEDs()
{
  //***********************************************
  //control the LEDs as per switches pushed
  //
  //initialize
  RedLEDflag = LEDon;

  //******************************
  //more than 2 switches pressed ?
  if (switchCount > 2)
  {
    GreenLEDFlag = LEDoff;
  }

  //******************************
  //no switches are pushed ?
  else if (Flag == 0)
  {
    GreenLEDFlag = LEDoff;
    RedLEDflag = LEDoff;
  }

  //******************************
  else
  {
    //check what switches are being pushed
    for (byte x = 0; x < 12; x++)
    {
      //for oscilloscope triggering
      PULSE9;

      //**************
      //are the correct switches are pushed ?
      if (Flag == question[x] + answer[x])
      {
        GreenLEDFlag = LEDon;
        RedLEDflag = LEDoff;

        //we found them, no need to go further
        break;
      }

      //**************
      //is 1 question switch is pushed ?
      else if (Flag == question[x])
      {
        GreenLEDFlag = LEDoff;
        RedLEDflag = LEDoff;

        //we found it, no need to go further
        break;
      }

      //**************
      //is 1 answer switch is pushed ?
      else if (Flag == answer[x])
      {
        GreenLEDFlag = LEDoff;
        RedLEDflag = LEDoff;

        //we found it, no need to go further
        break;
      }

    } //END of for (byte x = 0; x < 12; x++)

  } //END of else()

  //***********************************************
  //update the LEDs and sound the buzzer as needed
  digitalWrite(GreenLED, GreenLEDFlag);
  digitalWrite(RedLED, RedLEDflag);

  //**************
  //correct buzzer sound
  if (GreenLEDFlag == LEDon)
  {
    tone(buzzer, 4000, 500);
  }

  //**************
  //wrong buzzer sound
  else if (RedLEDflag == LEDon)
  {
    tone(buzzer, 500, 500);
  }

  //***********************************************

} //END of  controlLEDs()


//*********************************************************************************
void checkSwitches()
{
  //scan all the switches to see if there are changes in state, act accordingly
  for (byte x = 0; x < numQuestions; x++)
  {
    //***********************************************
    //current Question switch
    currentState = digitalRead(pairNum[x].Qpin);

    //******************************
    //was there a change in state ?
    if (pairNum[x].lastStateQ != currentState)
    {
      //update to the new state
      pairNum[x].lastStateQ = currentState;

      //a switch has changed state, Flag it
      switchChangeFlag = ENABLED;

      //******************
      //was the switch PUSHED ?
      if (currentState == PUSHED)
      {
        switchCount++;

        //set the associated flag bit
        Flag = Flag | bit(pairNum[x].bitNumQ);
      }

      //******************
      //the switch was released
      else
      {
        switchCount--;

        //reset the associated flag bit
        Flag = Flag & ~bit(pairNum[x].bitNumQ);
      }

      //******************
      //print the Flag so we can see the total
      Serial.print(Flag);

      //print the number of switches being pressed
      Serial.print("\t Switches pressed = ");
      Serial.println(switchCount);

    } //END of  if (pairNum[x].lastStateQ != state)

    //***********************************************
    //current Answer switch
    currentState = digitalRead(pairNum[x].Apin);

    //******************************
    //was there a change in state ?
    if (pairNum[x].lastStateA != currentState)
    {
      //update to the new state
      pairNum[x].lastStateA = currentState;


      //a switch has changed state, Flag it
      switchChangeFlag = ENABLED;

      //******************
      //was the switch PUSHED ?
      if (currentState == PUSHED)
      {
        switchCount++;

        //set the associated flag bit
        Flag = Flag | bit(pairNum[x].bitNumA);
      }

      //******************
      //the switch was released
      else
      {
        switchCount--;

        //reset the associated flag bit
        Flag = Flag & ~bit(pairNum[x].bitNumA);
      }

      //******************
      //print the Flag so we can see the total
      Serial.print(Flag);

      //print the number of switches being pressed
      Serial.print("\t Switches pressed = ");
      Serial.println(switchCount);

    } //END of  if (pairNum[x].lastStateA != state)

  } //END of  for (byte x = 0; x < numQuestions; x++)

} //END of checkSwitches()

//*********************************************************************************
1 Like