MCP23017 + Photon Issues

Hi everyone,

I am using a MCP23017 for additional IO’s. I have everything wired up and working correctly, but I do notice that over time (1-3 days), the MCP23017 IO’s don’t work anymore. Now I know there where some I2C issues on the Photon, but even with 4.4 I am still having these issues.

I also noticed that once I have issues with the MCP23017, that the Photon responds extremely slowly. For example, I am reading some pins from the Photon and based if they are HIGH, then I start flashing the RGB LED at an interval of 200 ms. When I have issues with the MCP23017, the RGB doesnt blink at 200 ms anymore, probably more like 1.5 seconds. Also at this state the Photon is slow to read the Photons IO. So starting the RGB blinking process is very delayed.

On my code, basically every loop() I am writing to the MCP23017 and telling it to set a pin HIGH or LOW. I was wondering if this is maybe causing the issue? That I am simply writing too much data to the I2C bus?? I added a 100 ms delay to the loop, and it does make it better, but only extends the days before the MCP23017 hangs again.

I’ve setup a spare Photon with a MCP23017 and a simple LED to see if I can replicate the issue, or if something else in my code might be causing this.

Carsten

For the photon to be running slowly, it could be an interrupt that is firing often, slowing down the rest of the system. If you have any interrupt handlers in your code, try removing them to see if that helps.

No interrupts here… my test unit just crashed… here is the code:

#if defined (SPARK)
#include "Adafruit_MCP23017/Adafruit_MCP23017.h"
#else
#include <Wire.h>
#include "Adafruit_MCP23017.h"
#endif

Adafruit_MCP23017 mcp;

long interval = 500;
long previousMillis = 0; 
int ledState = LOW;

void setup() { 
    pinMode(D7, OUTPUT);
    
    mcp.begin();     

  for (int i=0; i <= 16; i++){
    mcp.pinMode(i, OUTPUT);
  }
 
}


void loop() {

    if(millis() - previousMillis > interval) {
        previousMillis = millis() ;
        
        ledState = !ledState;
        mcp.digitalWrite(0, ledState); 
        digitalWrite(D7, ledState);
        
    }

   mcp.digitalWrite(1, HIGH);

}

My next test is to remove the following line:

mcp.digitalWrite(1, HIGH);

Lets see what happens.

I`ve tried running the this i2c code on my mcp23017 really fast on a rgb led.
And can see by flicking my head that each led is going on for a few milliseconds .

void loop() {
// To blink the LED, first we’ll turn it on…

  digitalWrite(led2, HIGH);
  mcp.digitalWrite(0, HIGH);
  mcp.digitalWrite(8, LOW);
  // We'll leave it on for 1 second...
  delay(1);

  // Then we'll turn it off...

  digitalWrite(led2, LOW);
  mcp.digitalWrite(0, LOW);
  mcp.digitalWrite(8, HIGH);
  // Wait 1 second...
  delay(1);
  
}

The comment says leave it on for 1 second…but delay(1) will delay for 1 millisecond, try delay(1000).

It is the default blinkly program , with bit changed and i2c added , the point was to show that the bus can be pushed fast without any problems.

Understood, thanks for clarifying.

I removed mcp.digitalWrite(1, HIGH); from the main loop about 5 hours ago and its still running strong. Will leaving it running to see what happens.

How fast does loop() run on the Photon?

About 230kHz. Much faster than 0.3.4 on the core, which ran at ca. 200Hz, so 3 orders of magnitude faster. (And this speed improvement will come to the core with the 0.4.5 release.)

So even the delay(1); will create a significant slow down which might save the i2c bus?

Sure, makes sense, if the library doesn’t fully block until the I2C operation is complete.

My test unit exists of a MCP23017 + the Photon. I blink the D7 on the Photon and a pin on the MCP23017 rapidly at the same time (50ms).

After about 3-4 days, the MCP pin stops blinking and the D7 slows down. The video below is basically when it’s in the crippled state:

Hitting the reset button on the Photon doesnt resolve the issue. Only way to fix is to unplug the power and restart it.

I need help fixing this, because with this issue, I cannot continue my HVAC project :frowning:

Any help is greatly appreciated!

Doing this every 1 minute seems to resolve the issue temporarily:

Wire.beginTransmission(0x40);
Wire.endTransmission();
Wire.begin();

Everyone 1 minute is probably overkill… But it works so far. I will keep testing and report results!

Thanks to @bko for pointing this out in another thread.

2 Likes

My test unit died this AM. So after 7 days of running, even with the code above, it still died.

I was happy for a moment that we found a work around. But I guess not!

Can someone describe the exact issue with I2C on the STM32F205?

See section 2.3 of this document:

2 Likes

Do you have a schematic of how the Photon connects to the MCP23017? I understand by the look of your project it might be something you might sell or commercialize, so mainly I want to see if your running the MCP23017 at 5v with a level shifter, 3.3 to 5v (no shifting) or 3.3v with direct connections.

I am trying to use the MCP23017 aswell and a few things that came to mind is
-Are you using the internal pull resistors on the MCP23017 or anything custom?
-Are you using a shifter? (i2c is a pretty annoying protocol with it’s shifting)

For my circuit I plan on doing this

Photon running at 5.15v, (Logic at 3.3v), MCP running at 5.15v, level shifter from Adafruit specifically for I2C.(If this fails running optocouplers instead of the Adafruit. (PC817 x4)

or

External 3.3v PSU and running MCP23017 at 3.3 same supply as the Photon with a clean power supply. (Prob linear to prevent noise from switching sacrificing power savings…)

2.3.5 Both SDA and SCL maximum rise time (tr) violated when VDD_I2C bus
higher than ((VDD+0.3) / 0.7) V
Description
When an external legacy I2C bus voltage (VDD_I2C) is set to 5 V while the MCU is powered
from VDD, the internal 5-Volt tolerant circuitry is activated as soon the input voltage (VIN)
reaches the VDD + diode threshold level. An additional internal large capacitance then
prevents the external pull-up resistor (RP) from rising the SDA and SCL signals within the
maximum timing (tr) which is 300 ns in fast mode and 1000 ns in Standard mode.
The rise time (tr) is measured from VIL and VIH with levels set at 0.3VDD_I2C and
0.7VDD_I2C.
Workaround
The external VDD_I2C bus voltage should be limited to a maximum value of
((VDD+0.3) / 0.7) V. As a result, when the MCU is powered from VD

I’m running a test project which uses a mcp23017 and a mcp23008 , plus a i2c display and had no real problems , yet.
I power my mcp’s from 5v and connect the pull up resistors to 5v , and don’t use a level shifter.
The only thing a need to do is a wire.reset after the mcp.begins , if i don’t i get a system freeze when I send new code.