Switch Control

Hi, i am making a game whereby a random LED will light up (from 0-11) and if the corresponding switch is flipped, the LED will off and add one to the scoreboard (7-segments). Right now, when a random LED lights up, the program will wait until the correct switch is flipped before proceeding,. However, the LED just waits as the switch seems to only read once.

Switch used: DIP switches
I/O expander used: PCF8574p

The code for the LED generates 12 numbers that will not repeat the previous number

  char k, i;
    
    for(i = 0; i<12; i++){
      while(1){
        k = random(0, 12);
  
        if(inArray(k, i) != 1){
          break;
        }
      }
      num[i] = k;
      //Serial.println((int)k);     // Random Sequence, Stored in num[i]  //((int)k) : casting 
      delay(1000);
      DisplayLED(k);
    }
}

char inArray (char Rnum, char limit){//Check if generated Num is already in array
  char i;
  
  for(i=0; i<limit; i++){
    if(Rnum == num[i]){
      return 1;   //in array
    }
  }
  return 0;      //not in array
}

A switch/case is used to light each individual LED.
*ignore the while( c != 509){} lines.

void DisplayLED (int k) {

  expanderWrite3(B11111111);     //turns all the LED off (from 0-7)
  expanderWrite4(B11111111);     //turns all the LED off (from 8-11)
  
  int c = 0;
  c = readsw();
  
  switch (k) {                                     // A random gen. number goes to the corresponding case
      case 0:
        expanderWrite3(B11111110);
        readsw();
        while( c != 509){
          }
         delay(500);
        expanderWrite3(B11111111);
        break;    
      case 1:
        expanderWrite3(B11111101);
        readsw();
        while( c != 509){
          }        
        delay(500);
        expanderWrite3(B11111111);      
      break;
      case 2:
        expanderWrite3(B11111011);
        readsw();
        while( c !=510){
         }
        delay(500);
        expanderWrite3(B11111111);
      readsw();  
       break;
      case 3:
        expanderWrite3(B11110111);
        readsw();
        while( c !=509){
          }
        delay(500);
        expanderWrite3(B11111111);
      break;
      case 4:
        expanderWrite3(B11101111);
        readsw();
        while( c !=509){
         }
        delay(500);
        expanderWrite3(B11111111);
      break;
      case 5:
        expanderWrite3(B11011111);
        readsw();
        while( c !=509){
         }
        delay(500);
        expanderWrite3(B11111111);
      break;
      case 6:
        expanderWrite3(B10111111);
        readsw();
        while( c !=509){
         }
        delay(500);
        expanderWrite3(B11111111);
      break;
      case 7:
        expanderWrite3(B01111111);
        readsw();
        while( c !=509){
         }
        delay(500);
        expanderWrite3(B11111111);
      break;
      case 8:
        expanderWrite4(B01111111);
        readsw();
        while( c !=509){
         }
        delay(500);
        expanderWrite4(B11111111);
      break;
      case 9:
        expanderWrite4(B10111111);
        readsw();
        while( c !=509){
           // temp = readsw();
         }
        delay(500);
        expanderWrite4(B11111111);
      break;
      case 10:
        expanderWrite4(B11011111);
        readsw();
        while( c !=509){
         }
        delay(500);
        expanderWrite4(B11111111);
      break;
      case 11:
        expanderWrite4(B11101111);
        readsw();
        while( c !=509){
         }
        delay(500);
        expanderWrite4(B11111111);
      break;
    }
}

This is the read switch function that reads that gets the 2bytes.

int readsw (void){

  i2cRecData(expander7, 1, &swStatus1);             //Reads the switch (I/O address, bytes, to where)
  i2cRecData(expander8, 1, &swStatus2);
  swVal = swStatus1 + swStatus2;                           // Gets the total 2 byte value (max:510)
  return swVal;
  
}

The readsw() should be constantly reading the switch so that when any pin is flipped to high, it will go through the while() statement and wait until the correct switch is flipped and off the LED (eventually adding 1 to the score)

The I/O address are all correct and the program runs with no error. However, the readsw() function just reads once making the program stuck at the while loop forever. So what do i do to make it check the readsw() constantly?
I've tried adding in for loops within the readsw() function but it does not work.

Thanks in advance.

How is the readsw () function being called ?
Please post your complete program so that the use of the function can be seen in context.

Its called within the DisplayLED function. If you see the first code provided, its the void loop().

unsigned char num[12] = {0xff, 0xff, 0xff,
                         0xff, 0xff, 0xff,
                         0xff, 0xff, 0xff,
                         0xff, 0xff};
                         
unsigned char ranNum;


void setup() {
  Serial.begin(9600);
  randomSeed(analogRead(0));
  expand_Init();                                          //initialize i2C
}

void loop() {
  
  char k, i;
    
    for(i = 0; i<12; i++){
      while(1){
        k = random(0, 12);
  
        if(inArray(k, i) != 1){
          break;
        }
      }
      num[i] = k;
      Serial.println((int)k);     // Random Sequence, Stored in num[i]  //((int)k) : casting 
      delay(1000);
      DisplayLED(k);                                       
      
      
    }
}

char inArray (char Rnum, char limit){//Check if generated Num is already in array
  char i;
  
  for(i=0; i<limit; i++){
    if(Rnum == num[i]){
      return 1;   //in array
    }
  }
  return 0;      //not in array
}

void DisplayLED (int k) is a .cpp file or sub function and below is the full code that i currently have for it.

//#include the related libraries
  #define the expanders

byte swStatus1, swStatus2;
int swVal=0;

void DisplayLED (int k) {

  expanderWrite3(B11111111);     //turns all the LED off (from 0-7)
  expanderWrite4(B11111111);     //turns all the LED off (from 8-11)
  
  int c = 0;
  c = readsw();                                        
  
  switch (k) {                                     // A random gen. number goes to the corresponding case
      case 0:
        expanderWrite3(B11111110);                
        readsw();
        while( c != 509){
          }
         delay(500);
        expanderWrite3(B11111111);
        break;    
      case 1:
        expanderWrite3(B11111101);
        readsw();
        while( c != 509){
          }        
        delay(500);
        expanderWrite3(B11111111);      
      break;
      case 2:
        expanderWrite3(B11111011);
        readsw();
        while( c !=510){
         }
        delay(500);
        expanderWrite3(B11111111);
      readsw();  
       break;
      case 3:
        expanderWrite3(B11110111);
        readsw();
        while( c !=509){
          }
        delay(500);
        expanderWrite3(B11111111);
      break;
      case 4:
        expanderWrite3(B11101111);
        readsw();
        while( c !=509){
         }
        delay(500);
        expanderWrite3(B11111111);
      break;
      case 5:
        expanderWrite3(B11011111);
        readsw();
        while( c !=509){
         }
        delay(500);
        expanderWrite3(B11111111);
      break;
      case 6:
        expanderWrite3(B10111111);
        readsw();
        while( c !=509){
         }
        delay(500);
        expanderWrite3(B11111111);
      break;
      case 7:
        expanderWrite3(B01111111);
        readsw();
        while( c !=509){
         }
        delay(500);
        expanderWrite3(B11111111);
      break;
      case 8:
        expanderWrite4(B01111111);
        readsw();
        while( c !=509){
         }
        delay(500);
        expanderWrite4(B11111111);
      break;
      case 9:
        expanderWrite4(B10111111);
        readsw();
        while( c !=509){
         }
        delay(500);
        expanderWrite4(B11111111);
      break;
      case 10:
        expanderWrite4(B11011111);
        readsw();
        while( c !=509){
         }
        delay(500);
        expanderWrite4(B11111111);
      break;
      case 11:
        expanderWrite4(B11101111);
        readsw();
        while( c !=509){
         }
        delay(500);
        expanderWrite4(B11111111);
      break;
    }
int readsw (void){

  i2cRecData(expander7, 1, &swStatus1);             //Reads the switch (I/O address, bytes, to where)
  i2cRecData(expander8, 1, &swStatus2);
  swVal = swStatus1 + swStatus2;                           // Gets the total 2 byte value (max:510)
  return swVal;
  
 }
}

It seems to be very complicated code for a very simple project.

An array can hold the status of each LED (which can be set at random)
Another array can hold the status of each switch.
A little bit of code can iterate through the two arrays to see if they match. If they do, it can change the led status
And another piece of code lights up the leds based on their status.
And, of course, a piece of code to read and save the switch statuses.

...R

        while( c !=509){
         }

Unless c equals 509 when this while loop starts then it will never end. What is it meant to do ?

readsw() reads the switch status in terms of bytes, therefore the two switches would have a maximum of 510.
So by right, if each switch is set to high individually, the number would be 510 when all is low, 508 when only the first pin/switch is flipped and 504, 496 so on and so forth (well that's what is saw on Serial.println).

The while loop is to wait till the corresponding switch is flipped, than it will exit and off the LED and another LED will light up waiting for its corresponding switch to be flipped.

How will c change when the while loop is preventing other code being executed ?

      case 0:
        expanderWrite3(B11111110);
        c = readsw();
        while( c != 509){
            c = readsw();
            Serial.println(c);
          }
         delay(500);
        expanderWrite3(B11111111);
        break;

Alright, i somehow managed to get it to work. Once the LED lights up (random generated) the switch will be read the first time, if the while loop condition is not fulfilled, it will read the switch value again and again till it is satisfied.

if the while loop condition is not fulfilled, it will read the switch value again and again till it is satisfied.

That's better. Now the while loop can end, whereas before it never, could so the program would stall.

Thanks for the advice! :slight_smile: