How to change this function in to a non-blocking function?

How do I modify the getTheNumber() function to satisfy the statement below?? " This function blocks until the user is done typing the number. Try to rewrite it in a non-blocking fashion. For example, it could return -1 on every call as long as the user is not done typing the number. On the first call after the user is done it would return the valid value. If you manage to write everything non-blocking, then you loop() will restart very often, and the program will work with no significant latency."

Here is the code:

int getTheNumber()
{
    char buffer[4];
    // Input up to 3 numbers until we find a * or #
    int i=0;
    while (1)
    {
        char key = keypad.getKey();

        // If it's a number AND we have space left, add to our string
        if ('0' <= key && key <= '9' && i < 3)
        {
            buffer[i] = key;
            i++;        
        }
        // If it's a * or #, end
        else if ('#' == key && i > 0)
        {
            // Null terminate
            buffer[i] =0; 
            int value = atoi(buffer);
            break;
        }        
    }
    return atoi(buffer);
    }

Perhaps a bit easier would be to:

int getTheNumber()
{
int temporary = 0;

while (1)
{
char key = keypad.getKey();

if ('#' == key || '' == key)
{
return(temporary);
}
temporary = ((10
temporary) + key);
}

Paul

How do I make my coding look like yours? I need to key in 3 digits..

Based on your original code, get rid of the while loop. Define an invalid number that can be returned (in below code, -999 because that will not fit in three digits) and return that when input is not complete.

void loop()
{
  int number = getTheNumber();
  if(number != -999)
  {
    // do something
    Serial.print("the number is "); Serial.println(number);
  }
}

/*
  get number from keypad; terminate input with '#'
  returns:
    -999 if number not complete, else number entered
*/
int getTheNumber()
{
  static char buffer[4];
  // Input up to 3 numbers until we find a * or #
  static int i = 0;
  char key = keypad.getKey();

  // If it's a number AND we have space left, add to our string
  if ('0' <= key && key <= '9' && i < 3)
  {
    buffer[i] = key;
    i++;

    return -999;
  }
  // If it's a * or #, end
  else if ('#' == key && i > 0)
  {
    // Null terminate
    buffer[i] = 0;
    i = 0;
    int value = atoi(buffer);
    break;
  }
  return atoi(buffer);
}

Not compiled and not tested.

Note the use of static variables for the buffer and the index (i). They act like global variables from the perspective that they are not forgotten when you leave the function but have local scope so can not be accessed outside your function.

May I politely suggest to use a slightly better name for the variable 'i' in this case; e.g. 'index'. Single letter variables are acceptable for loops (while, for, ...) but with the above code you don't have a loop anymore.

The function works very well. However, when I try to call the function for the second time, It shows the values of the first call of the function. I need to be able to call a function, then do something , Then calling the function again, to do another thing. As I enter the number for the first function, the second function also appears to be taking the same number as the first function. How do I call the GetNumber () to be called multiple time, but taking in different numbers for different purpose??

Here is the code:

void loop()
{
  int stage1speed = getTheNumber();
  if(stage1speed != -999)
  {
  lcd.setCursor(2,0);
  lcd.print(stage1speed);
  lcd.print("sv");
  }

  int stage1time = getTheNumber();
  if(stage1time != -999)
  {
  lcd.setCursor(2,1);
  lcd.print(stage1time);
  lcd.print("sec");
  }
  
  
}


static char buffer[4];
  static int i = 0;
  
int getTheNumber()
{
  static char buffer[4];
  static int i = 0;
  char key = keypad.getKey();

  // If it's a number AND we have space left, add to our string
  if ('0' <= key && key <= '9' && i < 3)
  {
    buffer[i] = key;
    i++;

    return -999;
  }
  // If it's a * or #, end
  else if ('#' == key && i > 0)
  {
    // Null terminate
    buffer[i] = 0;
    i = 0;
    int value = atoi(buffer);
    
  }
  return atoi(buffer);
}

rjadkins:
How do I make my coding look like yours? I need to key in 3 digits..

That code lets you key in as many digits as you like. Test the final result for being outside your limits for value, not number of digits.

Paul

You need a little bit of logic in your loop(); only when the entry for stage1speed is completed, allow to enter stage1time, and so on.

void loop()
{
  static int stage1speed = -999;
  static int stage1time = -999;
  
  if(stage1speed == -999)
  {
    stage1speed = getTheNumber();
  }
  else
  {
    if(stage1time==-999)
    {
      stage1time = getTheNumber();
    }
  }

  if(stage1speed != -999)
  {
    lcd.setCursor(2,0);
    lcd.print(stage1speed);
    lcd.print("sv");
  }

  if(stage1time != -999)
  {
    lcd.setCursor(2,1);
    lcd.print(stage1time);
    lcd.print("sec");
  }


  if(stage1speed!=-999 && stage1time!=-999)
  {
    // do something
    delay(5000);
    // reset speed and time for next entry
    stage1speed = stage1time = -999;
  }

}

int getTheNumber()
{
  static char buffer[4];
  static int i = 0;
  char key = keypad.getKey();

  // If it's a number AND we have space left, add to our string
  if ('0' <= key && key <= '9' && i < 3)
  {
    buffer[i] = key;
    i++;

    return -999;
  }
  // If it's a * or #, end
  else if ('#' == key && i > 0)
  {
    // Null terminate
    buffer[i] = 0;
    i = 0;
    int value = atoi(buffer);
   
  }
  return atoi(buffer);
}

Not tested

I've removed the two variables that you had before the getTheNumber function as they were useless. And you should put the comments back that I placed before the function; it's part of documentation and you can e.g. straight away see that it returns -999 under what condition.

The above is one way; you can also implement a statemachine with e.g switch/case.
In case 1 you get the stage1speed, in case 2 you get the stage1time, in case 3 you do something with it, in case 4 you get stage2speed, in case 5 you get stage2time and so on.