Need some intuition on using interrupts with Capacitive Touc

Post here about your Arduino projects, get help - for Adafruit customers!

Moderators: adafruit_support_bill, adafruit

Please be positive and constructive with your questions and comments.
Locked
User avatar
sideshow_ben
 
Posts: 6
Joined: Thu Sep 26, 2013 2:26 pm

Need some intuition on using interrupts with Capacitive Touc

Post by sideshow_ben »

TL;DR: is there a way to use an interrupt on a digital pin to break into a long delay and make something happen?

I'm building a real-time map of the solar system (an "orrery") using 500 strip LEDs (APA102), a DS 3231 RTC, and a capacitive touch sensor (the MPR121 or CAP1188 breakout boards). I need some help understanding whether I need to use the IRQ function from the cap boards given how I want the code structured. Frankly, I just don't really understand interrupts despite a lot of reading.

I have just a few functions of interest inside the loop():

Code: Select all

void loop(){
   float t = readRTC();
   int n = readCap();
   if (n_touched>0) doFunctions(n);
   updatePlanets(t);
   // delay(10); // put a small pause?
}
The LED board only needs to update itself every 90 seconds, by computing new positions and moving a planet if needed. However, a user can touch one of 6 capacitive plates to do things like speed up or reset the motion. I realize that I can just poll the cap in the loop() function and internally tell the updatePlanets() function to only do something every 90 sec. What I'd like is to just sit idle inside the loop with a 90-sec delay, but have a capTouched event break into the delay and fun its appropriate function.

I have successfully coded the MRP121 reader with the board's IRQ, so that it only reads the actual touch once the board's IRQ fires:

Code: Select all

#define irqpin 4 // attach Arduino pin 4 to MPR121 IRQ out
boolean checkInterrupt(void){
  return digitalRead(irqpin);
}

int readTouchInputs() {
  if(!checkInterrupt()){ // did IRQ fire?      
    // Get the currently touched pads
    n_touched = cap.touched();
    //do a bunch of stuff
   ...
}
But I was hoping there was some clever way to put the checkInterrupt() into the main loop() to interrupt a 90-sec delay and call readTouchInputs().

So questions.

1. Is this even possible?

2. If so, what would a skeleton code in the loop() function look like to do this?

Thanks a ton.

User avatar
adafruit_support_bill
 
Posts: 88097
Joined: Sat Feb 07, 2009 10:11 am

Re: Need some intuition on using interrupts with Capacitive

Post by adafruit_support_bill »

Something like:

Code: Select all

long lastUpdate = 0;

loop
{
	long now = millis(); // get current time
	while (now - lastUpdate < 90000)
	{
		if(!checkInterrupt()) // did IRQ fire?    
		{
			// Get the currently touched pads
			n_touched = cap.touched();
			//do a bunch of stuff
		}
	}
	float t = readRTC();
	int n = readCap();
	if (n_touched>0) doFunctions(n);
	updatePlanets(t);
	lastUpdate = millis();
}

User avatar
sideshow_ben
 
Posts: 6
Joined: Thu Sep 26, 2013 2:26 pm

Re: Need some intuition on using interrupts with Capacitive

Post by sideshow_ben »

Derp. That makes total sense.

I suppose there isn't a way to have an interrupt wake up a system without constantly polling it. So "idle" just really means "the only thing happening in the whole code is asking whether the interrupt fired every n millisec.".

User avatar
adafruit_support_bill
 
Posts: 88097
Joined: Sat Feb 07, 2009 10:11 am

Re: Need some intuition on using interrupts with Capacitive

Post by adafruit_support_bill »

You can attach an interrupt to a pin and write an interrupt handler for it: https://www.arduino.cc/reference/en/lan ... interrupt/

But you really need to keep the code in the interrupt handler as minimal as possible to avoid causing other issues. A common technique is to set a flag in the interrupt handler and poll the flag (instead of the pin) in your loop. The advantage of polling the flag instead of the pin is that the interrupt will guarantee that the touch event is not missed if you are doing something else in your loop such as updating the display.

There is no shame in polling when your CPU has nothing else to do. Think of it as an 'active delay'. Calling the delay() function should be avoided. It is pretty much guaranteed to waste CPU cycles - even if there is real work to do.

For more on the subject see:
https://learn.adafruit.com/multi-taskin ... ino-part-1
https://learn.adafruit.com/multi-taskin ... ino-part-2
https://learn.adafruit.com/multi-taskin ... ino-part-3

User avatar
sideshow_ben
 
Posts: 6
Joined: Thu Sep 26, 2013 2:26 pm

Re: Need some intuition on using interrupts with Capacitive

Post by sideshow_ben »

Thanks for all these ideas. I did actually spend a few hours trying to attach an interrupt to the IRQ out from the MPR121 board, exactly as suggested on the page you linked (https://www.arduino.cc/reference/en/lan ... interrupt/) and was not able to get that to work correctly. In one case, if I touched a lead, the code went into permanent "you've touched N" even after I released it. I guess I should revisit.

Locked
Please be positive and constructive with your questions and comments.

Return to “Arduino”