Storing values from attachInterrupt()

I am trying to store multiple numbers entered from a capacitive key pad (made by sparkfun).

They’ve supplied some starter code (does all of the i2c heavy lifting) from which I am trying to build off of for my project.

In essence, they have it set up to print one digit that corresponds to the number pressed and this works great. However, I would like to store multiple numbers (i.e. press “2,5” and I would like to store “25” as either an int, char or String - either way it will hopefully end up logged on an sdcard).
I would like the getNumber() function to return a value (i could then run the getNumber function inside a for loop that would store the values outputted by getNumber into an array). I am stuck because attachInterrupt() calls a function (in this case getNumber) but this function is NOT allowed to return anything. Is there anyway of storing this value? My best guess at this point is probably to write the value temporarily to EEPROM and then read it out in a second function that opens the sdwrite functionality. Is writing to memory a feasible solution or is there a ‘better’ way?

Here’s the setup() and getNumber() functions:

void setup()
{
//make sure the interrupt pin is an input and pulled high
pinMode(irqPin, INPUT);
digitalWrite(irqPin, HIGH);

//for testing purposes
pinMode(ledPin, OUTPUT);

//configure serial out
Serial.begin(9600);

// initalize I2C bus. Wiring lib not used.
i2cInit();

// initialize mpr121
mpr121QuickConfig();

// Create and interrupt to trigger when a button
// is hit, the IRQ pin goes low, and the function getNumber is run.
attachInterrupt(0,getNumber,LOW);

// prints ‘Ready…’ when you can start hitting numbers
Serial.println(“Ready…”);
}

void getNumber()
{
int touchNumber = 0;
uint16_t touchstatus;
char digits;

touchstatus = getTouchStatus();

for (int j=0; j<12; j++) // Check how many electrodes were pressed
{
if ((touchstatus & (1<<j)))
touchNumber++;
}

// check to see what touchNumber is equal to
Serial.println(touchNumber);

if (touchNumber == 1)
{
if (touchstatus & (1<<SEVEN))
{
digits = ‘7’;
}
else if (touchstatus & (1<<FOUR))
{
digits = ‘4’;
}
else if (touchstatus & (1<<ONE))
{
digits = ‘1’;
}
else if (touchstatus & (1<<EIGHT))
{
digits = ‘8’;
}
else if (touchstatus & (1<<FIVE))
{
digits = ‘5’;
}
else if (touchstatus & (1<<TWO))
{
digits = ‘2’;
}
else if (touchstatus & (1<<NINE))
{
digits = ‘9’;
}
else if (touchstatus & (1<<SIX))
{
digits = ‘6’;
}
else if (touchstatus & (1<<THREE))
{
digits = ‘3’;
}
//Serial.println(touchstatus, HEX);
Serial.println(digits);
//Serial.println(“end”);
}
//do nothing if more than one button is pressed, or if all are released
else if (touchNumber == 0)
Serial.println(“touch number is 0”);
else
Serial.print(touchNumber); // this should be the same thing as saying return touch; (last line of script)

}

/* getTouchStatus() will return a 16-bit value that relates the
current touched status of each button. The LSB represents electrodes
0-7 (bit 0 = electrode 0), and the lowest 4 bits of the MSB
represent electrods 8-11. A 1 means a button is being touched.*/
int getTouchStatus()
{
int touch;

touch = mpr121Read(0x01) << 8;
touch |= mpr121Read(0x00); //note: “x |= y” is the same as “x = x | y”

Serial.println(touch) //for debugging
return touch;
}

Why are you using an interrupt for this instead of polling?

Arrch: Why are you using an interrupt for this instead of polling?

Because I assumed the manufacturer of the device who also supplied the starter code would have implemented the most reliable way of using this device. I've tried changing certain settings and the mpr121 chip doesn't seem to like my changes so I've tried to stick with what's been outlined.

I'll check out polling as an alternative, thanks ! (this is my first arduino project so please bear with me).

sakotturi: Because I assumed the manufacturer of the device who also supplied the starter code would have implemented the most reliable way of using this device.

The fact that the manufacturer of the device supplied starter code that has Serial prints in an ISR tells me that their code probably should only be used to learn from, not implement.

I ‘solved’ this issue by creating a char for each digit I wanted stored:

// initialize chars for future numbers
char firstNum; 
char secondNum; 
char thirdNum;

followed by a boolean that will change from false to true after its corresponding number is stored:

 // initialize the existence of the previous three numbers to false
boolean firstNumExist = false; 
boolean secondNumExist = false; 
boolean thirdNumExist = false;

then, in getNumber() I set the firstNum to digits if it didn’t already exist. if firstNum == true, then set current digit to the second digit etc.

 if (firstNumExist == false)
 {
      firstNum = digits;
      firstNumExist = true; 
                                    
 }
 else if (firstNumExist == true && secondNumExist == false)
 {
   secondNum = digits; 
   secondNumExist = true; 
}
else if ( firstNumExist == true && secondNumExist == true && thirdNumExist == false)
{
  thirdNum = digits; 
  thirdNumExist = true;
} 
if ( firstNumExist == true && secondNumExist == true && thirdNumExist == true)
{
  // once all the desired numbers are inputed, perform the desired action with them. 
  // can potentially write to sd card here or do it later outside of getNumber()
  Serial.print("Subject number is:"); 
  Serial.print(firstNum); 
  Serial.println(secondNum);
  Serial.print("Event number is:"); 
  Serial.println(thirdNum); 
   
   // once all action is performed on the numbers, reset the existence of of the number markers to false                               
  firstNumExist = false; 
  secondNumExist = false; 
  thirdNumExist = false; 
  // now ready for next subject and event. 
}

the entire getNumber function reads:

void getNumber()
{


  int touchNumber = 0;
  uint16_t touchstatus;
  char digits;
  
		touchstatus = getTouchStatus();

		for(int j=0; j<12; j++)  // Check how many electrodes were pressed
		  {
		    if ((touchstatus & (1<<j)))
		      touchNumber++;
		  }

		  		if (touchNumber == 1)
				  {
				    if (touchstatus & (1<<SEVEN))
				    {
				      digits = '7';
				    }
				    else if (touchstatus & (1<<FOUR))
				    {
				      digits = '4';
				    }
				    else if (touchstatus & (1<<ONE))
				    {
				      digits = '1';
				    }
				    else if (touchstatus & (1<<EIGHT))
				    {
				      digits = '8';
				    }
				    else if (touchstatus & (1<<FIVE))
				    {
				      digits = '5';
				    }
				    else if (touchstatus & (1<<TWO))
				    {
				      digits = '2';
				    }
				    else if (touchstatus & (1<<NINE))
				    {
				      digits = '9';
				    }
				    else if (touchstatus & (1<<SIX))
				    {
				      digits = '6';
				    }
				    else if (touchstatus & (1<<THREE))
				    {
				      digits = '3';
				    }

				   // Serial.println(digits);
				    
                                    if (firstNumExist == false)
                                    {
                                      firstNum = digits;
                                      firstNumExist = true; 
                                    //  Serial.print("firstNum is:");
                                    //  Serial.println(firstNum);  
                                    }
                                    else if (firstNumExist == true && secondNumExist == false)
                                    {
                                      secondNum = digits; 
                                      secondNumExist = true; 
                                    //  Serial.print("secondNum is:");
                                    //  Serial.println(secondNum); 
                                    }
                                    else if ( firstNumExist == true && secondNumExist == true && thirdNumExist == false)
                                    {
                                      thirdNum = digits; 
                                      thirdNumExist = true;
                                    //  Serial.print("thirdNum is:");
                                    //  Serial.println(thirdNum);  
                                    } 
                                   if ( firstNumExist == true && secondNumExist == true && thirdNumExist == true)
                                   {
                                       // once all the desired numbers are inputed, perform the desired action with them. 
                                        // can potentially write to sd card here or do it later outside of getNumber()
                                     Serial.print("Subject number is:"); 
                                     Serial.print(firstNum); 
                                     Serial.println(secondNum);
                                     Serial.print("Event number is:"); 
                                     Serial.println(thirdNum); 
                                        // once all action is performed on the numbers, reset the existence of of the number markers to false  
                                     firstNumExist = false; 
                                     secondNumExist = false; 
                                     thirdNumExist = false; 
                                       // now ready for next subject and event. 
                                     
                                   }  
				  //do nothing if more than one button is pressed, or if all are released
				  else if (touchNumber == 0){
	                           //Serial.println("touch number is 0");                          
	                          } 
				  else{
	                            //Serial.print("touchNumber is:");
				    //Serial.print(touchNumber);    // this should be the same thing as saying return touch; (last line of script)
	                          }
  
                                }  
  
}  

/* getTouchStatus() will return a 16-bit value that relates the
current touched status of each button. The LSB represents electrodes
0-7 (bit 0 = electrode 0), and the lowest 4 bits of the MSB
represent electrods 8-11. A 1 means a button is being touched.*/
int getTouchStatus()
{
  int touch;
  
  touch = mpr121Read(0x01) << 8;
  touch |= mpr121Read(0x00);		//note: "x |= y" is the same as "x = x | y"
 // Serial.print("touch is:");		
  //Serial.println(touch);		//for debugging
  return touch;
}

this is still pretty rough and i will do a lot of fault tolerance to deal with weird input. I think I need to add a button ie. “enter”, once I have my desired numbers entered to confirm writing to an sdcard to avoid writing garbage (if i enter one number too many then everything is shifted one off…). Ideally a little screen (calculator type thing) that displays numbers before being entered is one idea). but we’ll see where it goes.

hopefully anyone else who uses this touch shield can find this helpful. (note, if you are using this, make sure you’ve downloaded the necessary libs and .h files the manufacturer also provides: http://dlnmh9ip6v2uc.cloudfront.net/datasheets/Dev/Arduino/Shields/Touch_Shield_Example.zip )

thank you those who chipped in with words of advice as i embark into this new arduino world. hopefully one day I will know how to build this from scratch w/o starter code crutches.

Welcome to the world of microprocessors!

For future reference, some reading about interrupts:

http://www.gammon.com.au/interrupts

Also the IDE has an "auto format" feature. That might make your code look neater.

When their example was written you could more-or-less get away with printing inside an ISR. Not as much these days.

You may want to read up on doing things in loops rather than this sort of thing:

else if ( firstNumExist == true && secondNumExist == true && thirdNumExist == false)

That would get tedious with 10 numbers wouldn't it? You just need a counter saying which number you are up to.

You may want to read up on doing things in loops rather than this sort of thing:

And read up on arrays.