ESP8266 with multiple MCP23017 on i2c: detect which chip and pin raised the interruptServiceRoutine

Ladies and gents,

I'm building an ESP8266 based system that connects to wifi and offers the ability to define the port configuration of up to 8 MCP23017 port expanders to react as outputs on websockets.
All works great so far.

Now i want to extend the project to also allow setting up the up to 128 MCP23017 i/Os as outputs OR Inputs by the user per REST API.

To be able to react on those - runtime (re)defined port configurations i need to have an way to get the Interrupts of each of those pins and figure out, which "button was pressed / released".

So it is NOT an option to assign the IOs to ISR in code as the user might reconfigure the setup in case he wants to reconnect the LEDs / Buttons in a different way.

For the output config for instance:

  1. i read the config from disk and setup wifi, websocket client, and port configurations
  2. i connect to Wifi
  3. i connect to websocket server
  4. i subscribe to websocket events and declare on which received value which LED (connected to any of the MCP23017 GPIOs) should switch on. This definition is included in the config from step 1 and can be redefined during runtime by a REST PUT request to /config sending a new configuration and resetting the system afterwards.

Example Config:

{
    "system": {
        "hostname": "myPanel"
    },
    "server": {
        "address": "192.168.178.5",
        "port": 2048,
        "path": "/fsuipc",
        "protocol": "fsuipc",
        "reconnectInterval": 5000
    },
    "io": [
        {
            "i2cAddress": 32,
            "out": [
                {
                    "port": 6,
                    "variable": "ParkingBrake_Position"
                },
                {
                    "port": 7,
                    "variable": "SWS_LIGHTING_Switch_Light_Landing",
                    "truthyValue": 2
                },
                {
                    "port": 16,
                    "variable": "A320_Neo_MFD_Range"
                },
                {
                    "port": 17,
                    "variable": "A320_Neo_EFIS_RANGE"
                },
                {
                    "port": 6,
                    "variable": "Sim_Paused",
                    "address": 612,
                    "type": "uint",
                    "size": 2,
                    "truthyValue": 4
                },
                {
                    "port": 17,
                    "variable": "parking",
                    "address": 3018,
                    "type": "uint",
                    "size": 2
                },
                {
                    "port": 7,
                    "variable": "fuelpump",
                    "address": 12548,
                    "type": "uint",
                    "size": 1
                }
            ],
            "in": [
                {
                    "port": 14,
                    "variable": "APU Start Switch"
                },
                {
                    "port": 15,
                    "variable": "APU Master Switch"
                }
            ]
        },
        {
            "i2cAddress": 38,
            "out": [
                {
                    "port": 12,
                    "variable": "APU Master Switch"
                },
                {
                    "port": 13,
                    "variable": "APU Start Switch"
                }
            ]
        }
    ]
}

So now i want to be able to fire an event in case on MCP23017 i2C Address 32 Port 14 a button is pressed (falling edge) so that i'm able to send a websocket message referring to the defined variable "APU Start Switch".

Do you already have any tutorial, guidance etc. to get into that?

Thanks a lot and best regards,

  Joe

I've use that chip, without interrupts and without a library.

Have you hit a wall reading

which claims to lead to a library supporting use of the interrupt capabilities of the chip?

I admit I read all about it in the data sheet, eyes glazing over and usually waking up with the cat on my face, but my assumption was that it is all in there, and mebbe someone had rolled it up nicely.

Perhaps the examples that come with the library would be informative.

I also assume you are familiar/experienced with using interrrupts. Which is why I am not bothering to ask why you are planning on using them.

HTH

Oh, and welcome to the fora @joeherwig!

a7

What's your problem? You read the registers and compare the previous and current states until you find the changed pin(s). Then look up the related action in the config.

If you want to use interrupts then connect all interrupt pins to one GPIO on your controller. If a difference occurs then that pin goes LOW and you can start searching the changed pin.

1 Like

Further since it would be ill-advised to do that I2C polling in the ISR, you'd have to just set a flag variable to be picked up in the non-ISR code on every iteration of the loop() function. So, you might as well just poll the GPIO in loop() instead and forget about using interrupts as they offer no advantage here. When you detect the GPIO going LOW, start polling the devices to see which one(s) caused it.

1 Like

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