Help Making Timer Project; Function Fails

I am trying to make a programmable timer. I have more about it here: http://forum.arduino.cc/index.php?topic=247174.msg1766691#msg1766691

Now I have it all put together and stuff. But my program isn’t working correctly. What it should do that it isn’t is one: it should see if I press the # button on a keypad. I do, it doesn’t. Upon doing this, it is supposed to reset the timer to the default 0300 seconds.
Next, it should tell if I press the * button. It does. But it should also let me insert a new time in when I do. It don’t. I have added some extra code to see where the problems lie. It is acting like it’s scanning the buttons as it should, but it’s not registering them.

I’ve traced a few bugs back to the multiplexer I have; it was disabling it when it wasn’t supposed to. I have it set to enable the multiplexer just before the initial scan, then disable it afterward. I tried to see if it was disabling it. It wasn’t. So I tried to move the part of the code that tests for # to before the part that tests *. Pressing # still does nothing. But pressing # will execute part of the code that resets the time (it beeps three times) before executing the correct code (beeps again) and still failing. In the following code, you can see where I commented out the code that tests for #.

// define numbers, buttons
const int numbers[] = {0b11111100,0b01100000,0b11011010,0b11110010,0b01100110,0b10110110,0b00111110,0b11100000,0b11111110,0b11100110}; // 0-9
const int buttons[] = {7,0,4,8,1,5,9,2,6,10,3,11}; //0, 1, 2, 3, 4, 5, 6, 7, 8, 9, *, #

// set the enable pins on both shift registers
const int en1 = 10; // set low when sending data, display
const int en2 = A2; // same as above, Mux

// these are the digits on the display
const int a1 = 2;
const int a2 = 3;
const int a3 = 4;
const int a4 = 5;

//data, clock, buttons, mux enable
const int sda = 7;
const int sck = 8;
const int sig = A0;
const int me = A1;

//set the digits time
int a = 0; //a-d are defualt time
int b = 3;
int c = 0;
int d = 0;
int e = 0; //temporary storage
int f = 0; // ^
int g = 0; // ^^
int h = 0; // ^^^
int done = 0; //^^^^

//to remember which button we're on
int button;

//buzzer
const int buzzer = 13;

//We'll need these for timing
unsigned long now; //for the millis() function
unsigned long wait; //for the fail system
int seconds;

void setup(){
  pinMode(en1,OUTPUT); //enable 1
  pinMode(en2,OUTPUT); //enable 2
  pinMode(me,OUTPUT); //Mux Enable
  pinMode(a1,OUTPUT); //digit one
  pinMode(a2,OUTPUT); //digit two
  pinMode(a3,OUTPUT); //digit three
  pinMode(a4,OUTPUT); //digit four
  pinMode(sda,OUTPUT); //data out
  pinMode(sck,OUTPUT); //clock
  pinMode(sig,INPUT); //button read
  pinMode(buzzer,OUTPUT); //buzzer
  digitalWrite(buzzer,0); //make sure buzzer is off initially
  digitalWrite(en1,1); //stop any random write cycle to the registers
  digitalWrite(en2,1);
  delay(10); //just here to compensate for propegation; can be removed
  digitalWrite(en1,0); //write all 0's to both registers
  digitalWrite(en2,0);
  shiftOut(sda,sck,LSBFIRST,0);
  digitalWrite(en1,1);
  digitalWrite(en2,1);
  digitalWrite(me,0); //disable the mux
}

void loop(){
  now=millis();
  
  while(millis() - now < 1000){ //while one second has not passed, strobe the time to the display
    digitalWrite(en1,0);
    shiftOut(sda,sck,LSBFIRST,numbers[a]);
    digitalWrite(a1,1);digitalWrite(a2,1);digitalWrite(a3,1);digitalWrite(a4,1);
    digitalWrite(en1,1);
    digitalWrite(a1,0);digitalWrite(a2,1);digitalWrite(a3,1);digitalWrite(a4,1);
    //delay(1);
    digitalWrite(en1,0);
    shiftOut(sda,sck,LSBFIRST,numbers[b]);
    digitalWrite(a1,1);digitalWrite(a2,1);digitalWrite(a3,1);digitalWrite(a4,1);
    digitalWrite(en1,1);
    digitalWrite(a1,1);digitalWrite(a2,0);digitalWrite(a3,1);digitalWrite(a4,1);
    //delay(1);
    digitalWrite(en1,0);
    shiftOut(sda,sck,LSBFIRST,numbers[c]);
    digitalWrite(a1,1);digitalWrite(a2,1);digitalWrite(a3,1);digitalWrite(a4,1);
    digitalWrite(en1,1);
    digitalWrite(a1,1);digitalWrite(a2,1);digitalWrite(a3,0);digitalWrite(a4,1);
    //delay(1);
    digitalWrite(en1,0);
    shiftOut(sda,sck,LSBFIRST,numbers[d]);
    digitalWrite(a1,1);digitalWrite(a2,1);digitalWrite(a3,1);digitalWrite(a4,1);
    digitalWrite(en1,1);
    digitalWrite(a1,1);digitalWrite(a2,1);digitalWrite(a3,1);digitalWrite(a4,0);
    //delay(1);
    //end of the strobing
    digitalWrite(me,1); //enable the mux
    button_read(); //test for a button press
    digitalWrite(me,0); //disable the mux
  }
  
  // subtract a second
 seconds = (a*1000)+(b*100)+(c*10)+d; //combine all digits to one number
if(seconds>0){ //is there still time left
  seconds--; //if so, subtract one
  a=seconds/1000; //the rest of the code puts the number back to four digits
  b=seconds/100 - (a*10);
  c=seconds/10 - (a*100) - (b*10);
  d=seconds - (a*1000) - (b*100) - (c*10);
}
}

void button_read(){
/*    digitalWrite(en2,0);
  shiftOut(sda,sck,LSBFIRST,11); //test the # button
  digitalWrite(en2,1);
  if(digitalRead(sig)==1){ //if # was pressed, reset timer to 0300 seconds
  for(int q=0;q<4;q++){
  digitalWrite(buzzer,1);
  delay(100);
  digitalWrite(buzzer,0);
  delay(100);
  }
    a=0;
    b=3;
    c=0;
    d=0;
}*/
  digitalWrite(en2,0);
  shiftOut(sda,sck,LSBFIRST,3); //look for * button
  digitalWrite(en2,1);
  if(digitalRead(sig)==1){ //was the * pressed
  digitalWrite(buzzer,1);
  delay(250);
  digitalWrite(buzzer,0);
  while(digitalRead(sig)==1){
    //wait
  }
  e=buttonn();
  if(e != 30){ //30 is the "cancel" code
    f=buttonn();
    if(f!=30){
      g=buttonn();
      if(g!=30){
        h=buttonn();
        if(h!=30){
          a=e; //a, b, c, d are the individual digits in the number
          b=f; //we are taking our temorary number and making it permanent
          c=g;
          d=h;
        }
      }
    }
  }
}
}
 
int buttonn(){
  wait = millis();
  while(millis() - wait < 10000){ //keep scanning buttons for no longer than 10 seconds
    for(button=0;button<12;button++){ //all buttons are read on a Mux controlled by a shift regiter
      digitalWrite(en2,0); //enable pin for shift register
      shiftOut(sda,sck,LSBFIRST,buttons[button]); //the buttons[] array allows to scan the buttons in order (0-9, *, #)
      digitalWrite(en2,1);
      if(digitalRead(sig)==1){ //if there's a hit
        digitalWrite(buzzer,1); //sound the buzzer
        delay(25);
        digitalWrite(buzzer,0);
        while(digitalRead(sig)==1){ //we don't want to fill all four variables with the same number by holding one button down
          //wait
        }
        if(button==10||button==11){ //these are my "cancel" buttons
          return 30; //exit code
        }
        else{
          return button; //pressed number
        }
      }
    }
  }
  return 30; //if 10 seconds passed
}

I can tell it’s executing the function button_read() correctly and that it’s nesting buttonn() correctly because after 10 seconds, it fails like it should and contenues the countdown. This is killing me.

Suggest you print out the actual button that was detected, at around line 171. This will enable you to confirm your hardware is being correctly and that the # key is associated with the button number you expect. Given the magic numbers scattered throughout your code it would also be a good idea to tell us what number that is.

Uhh.... which magic numbers? I did the best I could to spread comments around it explaining things. But I'll see what printing the buttons do.

EDIT
Okay, I started thining it may have been the Mux. So I headed over here (forgot to mention) to see what the heck I may have been doing wrong. The "EN" pin is active LOW, whereas the silkscreen indicates it's active HIGH. So I modified the code to reflect this. And low and behold, it's finally registering more buttons. Except that it's registering the wrong buttons.

In fact, the only button it's registering is *. And it is coming up different every time. It's registering as, well, any other button at any given time.

EDIT 2
Thank Karl Braun for the O-Scope. I traced the problem of random info to the shift register (to the mux). Still have no idea why it's working weirdly. But about to modify it.

EDIT 3
Stupid me didn't relize that Q0 on the shift register was bit 8. I changed the wiring to fix my error. And now all but the second column of buttons (2,5,8,0) don't work, along with #. * still wants to register as # randomly. The working numbers seem to register correctly , though printing them returns the array's index. Also, when in program mode, the * and # buttons act like numbers. Though pressing them causes weird things to happen, like missing digits (null?) and corrupted digits like little 'n' with a bar above it.

free-bee:
Uhh.... which magic numbers?

I mean all the places where the digits 0 .. 9 appear in your executable code, especially the places where the value doesn't represent a duration, and even more especially where it doesn't represent true/false or HIGH/LOW. What buttons do the values 10, 11, 30 represent?

If you haven't proved the hardware yet I recommend that you start with a much simpler sketch which eliminates all the display logic and just prints button detections to the serial port.

You mean like here, for example?

if(button==10||button==11)

I used 10 and 11 for * and #, respectively. In the array buttons (with an ‘s’), 10 and 11 do not correspond to a number, but to those symbols. Like here for example:

for(button=0;button<12;button++){ //all buttons are read on a Mux controlled by a shift regiter
      digitalWrite(en2,0); //enable pin for shift register
      shiftOut(sda,sck,LSBFIRST,buttons[button]); //the buttons[] array allows to scan the buttons in order (0-9, *, #)
      digitalWrite(en2,1);
      delay(1);

I’m using the number stored in button to scroll through the index for buttons. The number stored in the array for a given index is the address required to read the physical button for said index. The index is the button number we want, and the value at that index is where the button is. That’s why it so out of order:

const int buttons[] = {8,3,11,7,2,10,6,1,9,5,0,4}; //0, 1, 2, 3, 4, 5, 6, 7, 8, 9, *, #

^note that has been edited. It would be the same as before, but I got two wires crossed up on the shift register… again.

That 30, it was just a random number I decided to use for a “stop what you’re doing and go back” code.

Most of my issues were hardware related: not knowing that the enable pin on the mux was active low, trying to use the wrong bits on the shift register to control the mux, getting two wires crossed up on the shift register (shift registers - they’ll only cause you trouble).

But it’s finally working. I got all hardware bugs worked out (except one, which I worked around software wise), and all coding bugs worked out (I think). I may add a few more edits before calling it done.

// define numbers, buttons
const int numbers[] = {0b11111100,0b01100000,0b11011010,0b11110010,0b01100110,0b10110110,0b00111110,0b11100000,0b11111110,0b11100110}; // 0-9
const int buttons[] = {8,3,11,7,2,10,6,1,9,5,0,4}; //0, 1, 2, 3, 4, 5, 6, 7, 8, 9, *, #

// set the enable pins on both shift registers
const int en1 = 10; // set low when sending data, display
const int en2 = A2; // same as above, Mux

// these are the digits on the display
const int a1 = 2;
const int a2 = 3;
const int a3 = 4;
const int a4 = 5;

//data, clock, buttons, mux enable
const int sda = 7;
const int sck = 8;
const int sig = A0; //active LOW
const int me = A1;

//set the digits time
int a = 0; //a-d are defualt time
int b = 3;
int c = 0;
int d = 0;
int e = 0; //temporary storage
int f = 0; // ^
int g = 0; // ^^
int h = 0; // ^^^
int done = 0; //^^^^

//to remember which button we're on
int button;

//buzzer
const int buzzer = 13;

//We'll need these for timing
unsigned long now; //for the millis() function
unsigned long wait; //for the fail system
int seconds;

void setup(){
  pinMode(en1,OUTPUT); //enable 1
  pinMode(en2,OUTPUT); //enable 2
  pinMode(me,OUTPUT); //Mux Enable
  pinMode(a1,OUTPUT); //digit one
  pinMode(a2,OUTPUT); //digit two
  pinMode(a3,OUTPUT); //digit three
  pinMode(a4,OUTPUT); //digit four
  pinMode(sda,OUTPUT); //data out
  pinMode(sck,OUTPUT); //clock
  pinMode(sig,INPUT); //button read
  pinMode(buzzer,OUTPUT); //buzzer
  digitalWrite(buzzer,0); //make sure buzzer is off initially
  digitalWrite(en1,1); //stop any random write cycle to the registers
  digitalWrite(en2,1);
  delay(10); //just here to compensate for propegation; can be removed
  digitalWrite(en1,0); //write all 0's to both registers
  digitalWrite(en2,0);
  shiftOut(sda,sck,LSBFIRST,0);
  digitalWrite(en1,1);
  digitalWrite(en2,1);
  digitalWrite(me,1); //disable the mux
  
  //Serial.begin(9600);
}

void loop(){
  now=millis();
  
  while(millis() - now < 1000){ //while one second has not passed, strobe the time to the display
    digitalWrite(en1,0);
    shiftOut(sda,sck,LSBFIRST,numbers[a]);
    digitalWrite(a1,1);digitalWrite(a2,1);digitalWrite(a3,1);digitalWrite(a4,1);
    digitalWrite(en1,1);
    digitalWrite(a1,0);digitalWrite(a2,1);digitalWrite(a3,1);digitalWrite(a4,1);
    //delay(1);
    digitalWrite(en1,0);
    shiftOut(sda,sck,LSBFIRST,numbers[b]);
    digitalWrite(a1,1);digitalWrite(a2,1);digitalWrite(a3,1);digitalWrite(a4,1);
    digitalWrite(en1,1);
    digitalWrite(a1,1);digitalWrite(a2,0);digitalWrite(a3,1);digitalWrite(a4,1);
    //delay(1);
    digitalWrite(en1,0);
    shiftOut(sda,sck,LSBFIRST,numbers[c]);
    digitalWrite(a1,1);digitalWrite(a2,1);digitalWrite(a3,1);digitalWrite(a4,1);
    digitalWrite(en1,1);
    digitalWrite(a1,1);digitalWrite(a2,1);digitalWrite(a3,0);digitalWrite(a4,1);
    //delay(1);
    digitalWrite(en1,0);
    shiftOut(sda,sck,LSBFIRST,numbers[d]);
    digitalWrite(a1,1);digitalWrite(a2,1);digitalWrite(a3,1);digitalWrite(a4,1);
    digitalWrite(en1,1);
    digitalWrite(a1,1);digitalWrite(a2,1);digitalWrite(a3,1);digitalWrite(a4,0);
    delay(1);
    //end of the strobing
    digitalWrite(a4,1);
    digitalWrite(me,0); //enable the mux
    button_read(); //test for a button press
    digitalWrite(me,1); //disable the mux
  }
  
  // subtract a second
 seconds = (a*1000)+(b*100)+(c*10)+d; //combine all digits to one number
if(seconds>0){ //is there still time left
  seconds--; //if so, subtract one
  a=seconds/1000; //the rest of the code puts the number back to four digits
  b=seconds/100 - (a*10);
  c=seconds/10 - (a*100) - (b*10);
  d=seconds - (a*1000) - (b*100) - (c*10);
}
}

void button_read(){
  digitalWrite(en2,0);
  shiftOut(sda,sck,LSBFIRST,4); //test the # button
  digitalWrite(en2,1);
  //delay(1);
  if(digitalRead(sig)==1){ //if # was pressed, reset timer to 0300 seconds
  //Serial.println("#");
  for(int q=0;q<4;q++){
  digitalWrite(buzzer,1);
  delay(100);
  digitalWrite(buzzer,0);
  delay(100);
  }
    a=0;
    b=3;
    c=0;
    d=0;
}
  digitalWrite(en2,0);
  shiftOut(sda,sck,LSBFIRST,0); //look for * button
  digitalWrite(en2,1);
  delay(1);
  if(digitalRead(sig)==1){ //was the * pressed
  //Serial.println("*");
  digitalWrite(buzzer,1);
  delay(250);
  digitalWrite(buzzer,0);
  while(digitalRead(sig)==1){
    //wait
  }
  e=buttonn();
  if(e != 30){ //30 is the "cancel" code
    f=buttonn();
    if(f!=30){
      g=buttonn();
      if(g!=30){
        h=buttonn();
        if(h!=30){
          a=e; //a, b, c, d are the individual digits in the number
          b=f; //we are taking our temorary number and making it permanent
          c=g;
          d=h+1;
        }
      }
    }
  }
}
}
 
int buttonn(){
  wait = millis();
  while(millis() - wait < 20000){ //keep scanning buttons for no longer than 20 seconds
    for(button=0;button<12;button++){ //all buttons are read on a Mux controlled by a shift regiter
      digitalWrite(en2,0); //enable pin for shift register
      shiftOut(sda,sck,LSBFIRST,buttons[button]); //the buttons[] array allows to scan the buttons in order (0-9, *, #)
      digitalWrite(en2,1);
      delay(1);
      if(digitalRead(sig)==1){ //if there's a hit
      //Serial.println(button,DEC); //this is returning the index number, not the value corresponding to it
        digitalWrite(buzzer,1); //sound the buzzer
        delay(25);
        digitalWrite(buzzer,0);
        while(digitalRead(sig)==1){ //we don't want to fill all four variables with the same number by holding one button down
          //wait
        }
        if(button==10||button==11){ //these are my "cancel" buttons
        for(int q=0;q<5;q++){
          digitalWrite(buzzer,1);
          delay(10);
          digitalWrite(buzzer,0);
          delay(10);
        }
          return 30; //exit code
        }
        else{
          return button; //pressed number
        }
      }
    }
  }
  return 30; //if 20 seconds passed
}