5 years, 3 months ago.

How to read MPR121 status registers from inside the interrupt ISR

I have been trying to work this problem out for several hours now with no luck. I am using a Nucleo F767ZI board and an MPR121 sensor for capacitive touch sensing. As a test program to ensure that the sensor worked, I had the micro controller continuously read the status register 0x00 (over i2c) in an infinite while loop and when one of the first three electrodes were touched, a corresponding LED would light up. This worked perfectly.

I am now attempting to modify the code to use InterruptIn so that the micro controller isn't continuously checking the status register. The sensor has an IRQ out pin pulled high until a change in the status of one of the electrodes is detected in which case it is pulled down until either register 0 or register 1 (the electrode status registers) is read from. When I run this code, the callback function is successfully called but when register 0 is read, it always seems to return 0, as if none of the electrodes were touched, yet it pulls the interrupt pin low correctly when touched, and resets when I attempt to read. I don't know if this would be a problem related to the sensor, or if the Nucleo board isn't reading the values correctly.

#include "mbed.h"
#include "MPR121.h"

//Serial pc(USBTX, USBRX);
DigitalOut red(PF_13);
DigitalOut green(PE_9);
DigitalOut blue(PE_11);

///if defined TARGET_LPC1768 || TARGET_LPC11U24
  I2C i2c(PB_9, PB_8);
  InterruptIn irq(PF_12);
  MPR121 touch_pad(i2c, irq, MPR121::ADDR_VSS);

void checkPads()
{   
    uint8_t value = touch_pad.readRegister(MPR121::ELE0_7_STAT);
        
        if(value % 2 < 1)
            red = 0;
        else
            red = 1;
            
        if(value % 4 < 2)
            green = 0;
        else
            green = 1;
        
        if(value % 8 < 4)
            blue = 0;
        else
            blue = 1;
}

void fallInterrupt()
{
    checkPads();
}

int main() 
{       
    touch_pad.init();
    touch_pad.enable();
    irq.fall(&fallInterrupt);
    
    while (1) {}
}

Essentially, if the 'checkPads()' function is moved to the while loop, it performs as expected, but moving it to the interrupt function causes it to not work properly, even though the fallInterrupt function is being called when expected. Any insight on the problem would be appreciated.

Sorry - I can't help on the problem, I don't know either the board or sensor and I can't see anything obviously wrong. But for future reference, if you do

<<code>>
your code
<</code>>

Then the formatting of the code will be displayed correctly. Without it it the formatting and which bits are comments gets lost making things a lot harder to read.

posted by Andy A 20 Jan 2017

Thinking about it can you try something a little different - Have the interrupt set a flag that the registers need to be checked and then in the main code look for that flag and then read the registers (and clear the flag obviously). I have no idea whether this is suitable for your final application or not but it would at least show that the problem is with the I2C read in an interrupt rather than being caused by only performing a single register read as opposed to constant register reads.

posted by Andy A 20 Jan 2017

Thank you for pointing this out to me, I have since fixed the formatting.

posted by Robert Cook 20 Jan 2017

1 Answer

5 years, 3 months ago.

One further thought, the library you are using for the touch sensor reads the status registers on an interrupt. You may want to try editing the library so that it's not clearing the status every interrupt. Commenting out line 99 should do that.

I am assuming the line 99 you are referring to is that of MPR121.cpp:

_irq->fall(this, &MPR121::handler);

The handler doesn't appear to set any of the registers to zero. I commented it out anyway just to test it and it doesn't fixed the problem. The flag idea however is one way to approach it and I had thought about it. There are other sensors though to consider in the project so I don't want to have the while loop constantly reading the status of each flag variable but if worset comes to worst it is certainly one way to go. I appreciate your suggestions!

posted by Robert Cook 20 Jan 2017