Trouble with interrupts

I’m working on a project with an ultrasonic rangefinder and I need to monitor the signal continuously at certain times. I have an LCD keypad shield and I’m making a menu style interface: pressing one button gives the level, another gives the maximum level reached, another the minimum, and so on.
When I press a certain button, I want the level to be displayed, and to be continuously updated as it is changed. Right now I can achieve this, but I can not read in any other button presses, so I am stuck at this one menu stage. Here’s the code:

#include <LCD4Bit_mod.h> 
LCD4Bit_mod lcd = LCD4Bit_mod(2); 

//Key message
char msgs[5][15] = {"  Menu 1     ", 
                    "Up Key OK    ", 
                    "Down Key OK  ", 
                    "  Menu 2     ", 
                    "Select Key OK" };
int  adc_key_val[5] ={30, 150, 360, 535, 760 };
int NUM_KEYS = 5;
int adc_key_in;
int key=-1;
int oldkey=-1;
const int pwPin = 12;
long pulse, inches, cm;
int level;
char newLevel[3];
volatile int state = CHANGE;

void setup()
{ 
  Serial.begin(9600);
  lcd.init();
  lcd.clear();
  lcd.printIn("Ultrasonic Level"); 
}

void loop() 
{
  adc_key_in = analogRead(0);      // read the value from the sensor  
  key = get_key(adc_key_in);         // convert into key press
  if (key != oldkey)               // if keypress is detected
  {
    delay(50);                       // wait for debounce time
    adc_key_in = analogRead(0);    // read the value from the sensor  
    key = get_key(adc_key_in);         // convert into key press
    if (key != oldkey)                        
    {                  
      oldkey = key;
      if (key >=0)
      {
        lcd.clear();
        lcd.cursorTo(1, 0);  //line=2, x=0
        lcd.printIn(msgs[key]);
      }
      if (key == 0)
          attachInterrupt(0, getPulse, CHANGE);
    }
  }
}
// Convert ADC value to key number
int get_key(unsigned int input)
{
  int k;
  for (k = 0; k < NUM_KEYS; k++)
  {
    if (input < adc_key_val[k])
    {
      return k;
    }
  }
  if (k >= NUM_KEYS)
    k = -1;     // No valid key pressed
  return k;
}

void getPulse()
{
    pulse = pulseIn(pwPin, HIGH);
    level = pulse/147;
    itoa(level, newLevel, 10);
    lcd.cursorTo(2,0);
    lcd.printIn("Level: ");
    lcd.printIn(newLevel);
}

When the key == 0 is where the interrupt is called.

When the key == 0 is where the interrupt is called.

Well no, that isn't really true. When key == 0, an interrupt is attached. When is the condition you expect key to become 0? Why not just attach the interrupt once in setup()?

Inside of your Interrupt Routine, you use both "level" and "pulse." The Arduino documentation says: "You should declare as volatile any variables that you modify within the attached function." Not sure it is related to what you are seeing, but might be worth fixing.

With the exception of the key == 0 check, your code is pretty much a copy/paste of the example for the shield. Does the original example work as expected?

When key becomes 0 is when a certain button is pressed. When I press this button I want to continuously monitor the level input from the sensor, so only interrupt at that time. I declared both level and pulse as volatile, but that was not related to the problem.
The example code worked fine before I started modifying it. I had it displaying the level with the press of a certain button, but I want the “real time” level displayed.

#include <LCD4Bit_mod.h> 
//create object to control an LCD.  
//number of lines in display=1
LCD4Bit_mod lcd = LCD4Bit_mod(2); 

//Key message
char msgs[5][15] = {"  Menu 1     ", 
                    "Up Key OK    ", 
                    "Down Key OK  ", 
                    "  Menu 2     ", 
                    "Select Key OK" };
int  adc_key_val[5] ={30, 150, 360, 535, 760 };
int NUM_KEYS = 5;
int adc_key_in;
int key=-1;
int oldkey=-1;
const int pwPin = 12;
volatile long pulse, inches, cm;
volatile int level;
char newLevel[4];
volatile int state = CHANGE;

void setup()
{ 
  Serial.begin(9600);
  lcd.init();
  lcd.clear();
  lcd.printIn("Ultrasonic Level"); 
  attachInterrupt(0, getPulse, CHANGE);
}

void loop() 
{
  noInterrupts();
  adc_key_in = analogRead(0);      // read the value from the sensor  
  key = get_key(adc_key_in);         // convert into key press
  if (key != oldkey)               // if keypress is detected
  {
    noInterrupts();
    delay(50);                       // wait for debounce time
    adc_key_in = analogRead(0);    // read the value from the sensor  
    key = get_key(adc_key_in);         // convert into key press
    if (key != oldkey)                        
    {                  
      oldkey = key;
      if (key >=0)
      {
        noInterrupts();
        lcd.clear();
        lcd.cursorTo(1, 0);  //line=2, x=0
        lcd.printIn(msgs[key]);
        Serial.print(key);
      }
      if (key == 0)
        interrupts();  
    }
  }
}
// Convert ADC value to key number
int get_key(unsigned int input)
{
  int k;
  for (k = 0; k < NUM_KEYS; k++)
  {
    if (input < adc_key_val[k])
    {
      return k;
    }
  }
  if (k >= NUM_KEYS)
    k = -1;     // No valid key pressed
  return k;
}

void getPulse()
{
    pulse = pulseIn(pwPin, HIGH);
    level = pulse/147;
    itoa(level, newLevel, 10);
    lcd.cursorTo(2,0);
    lcd.printIn("Level: ");
    lcd.printIn(newLevel);
}

I had it displaying the level with the press of a certain button, but I want the "real time" level displayed.

In your code, you only update the display when a button is being pressed.

Create a state variable that tracks what you want to display. Each time through loop(), update the display based on the current value in your state variable. When a key is pressed, change the value of the state variable.