Need some intuition on using interrupts with Capacitive Touc

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():

void loop(){
   float t = readRTC();
   int n = readCap();
   if (n_touched>0) doFunctions(n);
   // 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:

#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.

p.s. this is cross posted in the Adafruit Forum. I'll be sure to update one if I get useful info in the other, as a "public service"

You have to build the "clever" into your program, not add it later. Do not use "delay()".

The thing is, even if your switch drives an interrupt, the delay(90000); won't "terminate."
You need some kind of check, inside a less delay-based loop, sort of like:

  while (!elapsed(90000)) {
    if (buttonPushed()) {
      break;   // break out of timing loop
  if (buttonPushed()) {
    // button stuff
  } else {
    // 90s expired stuff

But at that point, it doesn't matter if your buttons have interrupts or not; the buttonPushed() function can check whether interrupts have happened, or it can "poll" the buttons, or whatever.

Ideally, the elapsed() function should probably use code like "Blink without delay", checking millis() against starttime+delaytime, but since you're not trying to do other things as well, it could be much simpler. Perhaps:

  for (int i=0; i<900; i++) { // loop 900 times.
    delay(100);  // sleep 0.1s (0.1s * 900 = 90s)
    // (note that a 0.1s delay in button response will go unnoticed by humans.)
    if (buttonPushed()) {

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.

this, however, is the more powerful overall solution. Keep looping through loop, which permits adding more functions as you go along, and assures that things that might need to happen outside of the loop will happen as well.

Why were you trying to avoid it?

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.