Arduino Pulse Reader

I tried to modify a programs, credits to this site Arduino Based Heart Rate Monitor Project. I tried adding a keypad for additional input but it seems that it is not working as imagined. Can somebody identify what I’m doing wrong?

# include <LiquidCrystal.h>
# include <Keypad.h>

LiquidCrystal lcd (13,12,11,10,9,8);
int in=A0; 
char a='0';
char b='0';
int count=0,i=0,k=0,rate=0;
int n=0;
char password[]={a,b};
char input [2];
unsigned long time2,time1;
unsigned long time;
const byte ROWS = 4;
const byte COLS = 4;
char keys[ROWS][COLS] ={
           {'1','2','3','A'},
           {'4','5','6','B'},
           {'7','8','9','C'},
           {'*','0','#','D'}
};

byte rowPins [ROWS] = {7,6,5,4};
byte colPins [COLS] = {3,2,1,0};
Keypad mykeypad = Keypad(makeKeymap(keys), rowPins, colPins,4,4);

void setup() {
  lcd.begin (16,2);
  lcd.print ("Pulse Reader");
  delay (5000);
  lcd.clear ();
  lcd.print("Press Any Button");
  // put your setup code here, to run once:

}

void loop() {
 char key = mykeypad.getKey();
 n=0;
 if (key){
 while(n==0){

    while (n==0){
    lcd.clear();
    lcd.print ("Enter Gender");
      if (key='A'){
     lcd.print("Male");
     input[n]='A';
     n=n+1;
     }
    if (key='B'){
     lcd.clear();
     lcd.print("Female");
     input[n]='B';
     n=n+1;
    }
    else {
     lcd.clear();
     lcd.print("Try Again");
    }
    }
  while (n==1){
  lcd.clear();
  lcd.print ("Enter Age");
  if (key='1'){
    lcd.print("18-35 Yrs Old");
    input[n]='1';
    n=n+1;
  }
  if (key='2'){
    lcd.clear();
    lcd.print("36-55");
    input[n]='2';
    n=n+1;
  }
  }
  while (n==2){
  lcd.clear();
  lcd.print("Press *");
  if (key='*')
  {
    k=0;
    lcd.clear();
    lcd.print("Please wait.......");
    while(k<15)
    {
     if(digitalRead(in))
     {
      if(k==0)
      time1=millis();
      k++;
      while(digitalRead(in));
     }
    }
      time2=millis();
      rate=time2-time1;
      rate=rate/5;
      rate=75000/rate;
      lcd.clear();
      lcd.print("Heart Beat Rate:");
      lcd.setCursor(0,1);
      delay (30000);
      lcd.print(rate);
      lcd.print(" ");
      lcd.write(1);      
      k=0;
      rate=0;
    }

  }
  }
  }
}

What does it do? What do you expect it to do?

Although there are valid use for while loops, this is more than likely not one of them. loop() already loops, so no need for while loops and while loops inside while loops.

The main problem is currently that you do not read the keypad while your in one of your inner while loops.

Read up on state machines. Entering the gender is one state, entering the age another one and measuring the 3rd one. You have something like that but it will be easier to use a switch/case to implement this; each time a state is completed, you can go to the next one.

sterretje:
What does it do? What do you expect it to do?

Although there are valid use for while loops, this is more than likely not one of them. loop() already loops, so no need for while loops and while loops inside while loops.

The main problem is currently that you do not read the keypad while your in one of your inner while loops.

Read up on state machines. Entering the gender is one state, entering the age another one and measuring the 3rd one. You have something like that but it will be easier to use a switch/case to implement this; each time a state is completed, you can go to the next one.

I'm sorry I forgot to add comments in it. You're right, it wont read the keypad. It goes straight to the reading function. Thank you for the reply, I'll follow what you advised.

For starters, something like this

#define SHOWTITLE 0
#define WAITSTARTBUTTON 1
#define GETGENDER 2
#define GETAGE 3
#define WAITSTARTMEASURE 4
#define MEASURE 5

...
...

void setup()
{
}

void loop()
{
  static byte currentState = SHOWTITLE;

  //char key = mykeypad.getKey();

  char key = NO_KEY;
  if (Serial.available() > 0)
  {
    key = Serial.read();
  }

  switch (currentState)
  {
    case SHOWTITLE:
      Serial.println("Pulse Reader");
      Serial.println("Press Any Button");
      currentState = WAITSTARTBUTTON;
      break;
    case WAITSTARTBUTTON:
      if (key != NO_KEY)
      {
        currentState = GETGENDER;
        Serial.println("Enter gender (A->male, B->Female");
      }
      break;
    case GETGENDER:
      switch (key)
      {
        case 'A':
          Serial.println("Male");
          currentState = GETAGE;
          Serial.println("Enter age (1->18 - 35 Yrs Old, 2->36 - 55 Yrs Old");
          break;
        case 'B':
          Serial.println("Female");
          Serial.println("Enter age (1->18 - 35 Yrs Old, 2->36 - 55 Yrs Old");
          currentState = GETAGE;
          break;
        case NO_KEY:
          // do nothing
          break;
        default:
          Serial.println("Try again");
          break;
      }
      break;
    case GETAGE:
      switch (key)
      {
        case '1':
          Serial.println("18 - 35 Yrs Old");
          Serial.println("Press * to start");
          currentState = WAITSTARTMEASURE;
          break;
        case '2':
          Serial.println("36 - 55 Yrs Old");
          Serial.println("Press * to start");
          currentState = WAITSTARTMEASURE;
          break;
        case NO_KEY:
          // do nothing
          break;
        default:
          Serial.println("Try again");
          break;
      }
      break;
    case WAITSTARTMEASURE:
      if (key == '*')
      {
        currentState = MEASURE;
      }
      break;
    case MEASURE:
      // do your measurement
      ...
      ...
      // back to showing title
      currentState = SHOWTITLE;
      break;
  }
}

It's a few more states. If needed (I would probably do so), create functions for each state to keep your loop small. The functions can return true to indicate that a step is completed or false if the step is not completed and based on that return value you can go to the next state.

The only thing you need to do is implement a (preferably non-blocking) measurement.

// Note that I used Serial to simulate the keypad and the LCD

It's a few more states. If needed (I would probably do so), create functions for each state to keep your loop small. The functions can return true to indicate that a step is completed or false if the step is not completed and based on that return value you can go to the next state.

The only thing you need to do is implement a (preferably non-blocking) measurement.

// Note that I used Serial to simulate the keypad and the LCD

Wow! I'll take note of that. That's definitely a great help. Here is the switch/case version of the program ( but haven't tried on the device).

void loop() {
char key = mykeypad.getKey();
n=0;
if (key){
 switch (key){
   
   case 'A':
   if (n==0){
   lcd.print("Male");
   input[n]='A';
   n=n+1;
   } 
   case 'B':
   if (n==0){
   lcd.clear();
   lcd.print("Female");
   input[n]='B';
   n=n+1;
   }  
   case '1':
   if (n==1){
   lcd.print("18-35 Yrs Old");
   input[n]='1';
   n=n+1;
   }
   case '2':
   if (n==1){
   lcd.clear();
   lcd.print("36-55");
   input[n]='2';
   n=n+1;
   }
   case '*':
   if (n==2){ 
   k=0;
   lcd.clear();
   lcd.print("Please wait.......");

   ......// reading pulse
   lcd.print(rate);

     }
   }
}
 if (n==0){
 lcd.clear();
 lcd.print ("Enter Gender");
 }
 if (n==1){
 lcd.clear();
 lcd.print ("Enter Age");
 }
 if (n==2){
 lcd.clear();
 lcd.print("Press *");
   }
 }