Multiple interrupt handling from MCP23017 to Uno

Hello,

I am building a machine which will need several sensors (Inputs) and pneumatic solenoids (Outputs). In search for low cost IO cards/expanders I found MCP23017 could do the job. I built the electronics with 8 MCP23017s with addresses from 0 till 7. Each MCP23017 has Port A defined as outputs and Port B as Inputs. All Inputs are pulled up.

All MCPs were connected to the Arduino Uno with I2C. Arduino was programmed using Adafruit_MCP23017.h library, to receive Input Data and Send Output data. For receiving and sending, my GUI was made in VB.net which sends a character “I” each 1ms (using timer) to the Arduino (serial comm). Each time Arduino gets this character, it checks and sends the sensor status to VB.net. For Outputs, whenever required, Vb.net sends a 65 character string with first 64 containing output status (0 or 1) and a specific 65th character “O” for Arduino to decipher end of line. When the output data is sent, VB.net stops the 1ms timer sending “I” and sends the Output data instead, and then restarts the 1ms timer.

So far so good. All works perfectly and I see the status of all sensors nearly real-time (1ms) and am able to send output data as and when required.

The question is - is it ok to keep checking for sensor data (Inputs) each 1ms? Or should I instead use interrupts? Honestly the Rx/Tx LEDs constantly blinking on the Uno somewhat scare me as if it’ll limit the reliability/longevity of the Uno.

Hence I started working on the interrupts. I configured the MCPs for Active Low interrupts using Since Uno had only 2 pins for interrupts, I joined all interrupts and connected them to Pin D2. Nothing works. If I connect only one MCP23017 interrupt (any 1 out of 8), it works seamlessly. I finally noticed that tying together up to 3 interrupts together works fine (could be any 3 out of 8). But the moment the 4th one is connected, Arduino stops accepting interrupts, OR MCPs stop giving out interrupts.

I then thought of combining these 8 interrupts using CD4068 - 8-input Nand gate. I fed all interrupts to the 8-inputs and connected the output to Arduino D2. As soon as any interrupt is received, the CD4068 goes high, but remains high and doesn’t come back to 0. I tried pulling down this output but it still doesn’t work.

This is where I am stuck right now.

Can you please help answering:
a) whether my decision to use interrupts is valid? Or should I continue working with 1ms timer to check inputs? Please keep in mind that the machine will be running 20 hrs a day and 300 days a year!

b) what am I doing wrong in combining the interrupts to get a single interrupt.

Hope you can help me out!!

Regards
Vinit

Yes

It won't

The MCP interrupt pin will remain high until the Arduino reads the inputs over i2c.

Thanks a lot for this reassurance.

You mean the MCP interrupt will remain LOW (configured to go Low on interrupt) until Arduino reads it over I2C and detaches the interrupt.

But if the input (interrupt) doesn’t go back to high, CD4068’s output won’t go back to low, the Arduino will never read it as an interrupt and MCP will never reset the interrupt. How should then the interrupts be combined to produce a single interrupt?

Just to clarify, how are the MCP23017 interrupts configured?

image

That should work with interrupts configured for open drain. Set as Active Low highs will fight against lows. Check the datasheet, you'll need a pullup if set for open drain.

As mentioned in my original post, I’m using Adafruit_MCP23017 library.

Using mcp[0-7]setupInterrupts(false,false,LOW)

Arguments:
false - Mirroring INTA and INTB is turned OFF
false - Interrupts pins are NOT floating or NOT Open Drain
LOW - Polarity of active interrupt signal

All Interrupt signals are at 4.7V (approximately) when second argument is false and 2.3V when it is True. Combining al interrupts by simply tying them together, they’re still at 4.7V. But combining by tying together and connecting to Arduino doesn’t trigger the interrupt on Arduino if more than 3 interrupts are connected.

Any ideas or suggestions?

Maybe it is necessary to send a command to the chip to clear the interrupt, not simply read the inputs. I may be getting confused with pcf8574/8575.

Why will the Arduino never read it as an interrupt? I think it would. I would attach an interrupt when the output of the CD4068 changes from LOW to HIGH (use RISING). When the interrupt pin of the MCP goes from HIGH toLOW, the CD4068 output will go from LOW to HIGH. The interrupt will be triggered. The interrupt routine can set a bool global variable to true to indicate that this occurred. In loop(), the bool variable is checked and if set, data needs to be read from the MCP and the interrupt cleared.

But all of this is unnecessary, because your Uno is not going to wear out due to frequent checking of the MCP inputs.

You're right, this is how it should work but astonishingly it doesn't! As soon as I change an input on any MCP, the output of CD4068 does go high (I've attached an LED on the output). And it remains high. The same output is connected to D2 of the Uno but it doesn't recognise this interrupt. I have tried attachInterrupt as "RISING" as well as "CHANGE". But the Uno doesn't wake up! I tried using optocouplers between the MCP interrupts and CD4068, nothing happened. I also tried optocoupler between CD4068 output and Uno D2 but still no use!

True! I think I'll leave this here and continue with 1ms checking of inputs though it's hard to accept something which is mean to work, not working!

Thanks for your help!

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