[Solved] MCP23017 and reset

I'm using two MCP23017 which control 16 dual LEDs (red-green).

During development of the sketch, things go wrong and I have to press reset. But sometime it seems like the two MCP23017 does not work well after the reset. I have to physical disconnect both I2C and power lines to them before the start acting normal again.

I'm using the Adafruit_MCP23017 library.

Bad chips?

Bad circuit more like.
What is yours?

Grumpy_Mike:
Bad circuit more like.
What is yours?

Sorry, but I do know understand what you mean by “What is yours?”.

The MCP23017 is mounted on a prototype PCB (the one with lots of hols you know).

I have created a test sketch for this card:

//#define BOARD_16X_DUAL_LED_DBG 1
#include <Board_16x_dual_led.h>

const uint8_t dualAdr1 = 0x24;
const uint8_t dualAdr2 = 0x25;

Board_16x_dual_led dualLed(dualAdr1, dualAdr2);

static const ledStatus states[LED_STATE_COUNT] = {LedRed, LedGreen, LedBoth, LedOff};

int freeRam() 
{
  extern int __heap_start, *__brkval;
  int v;
  return (int) &v - (__brkval == 0 ? (int) &__heap_start : (int) __brkval);
}

void setup()
{
  Serial.begin(9600);
  Serial.println(F("\n\n\nInitialzing..."));

  randomSeed(analogRead(A0));

  Serial.println(F("Initializing 16x Dual led board"));
  if (!dualLed.setup()) {
    Serial.println(F("FAiLED"));
    while (true) ;
  }

  Serial.print(F("Free ram="));
  Serial.println(freeRam());
}

void setled(const uint8_t ledno, ledStatus state)
{
  if (!dualLed.setLedStatus(ledno, state)) {
    Serial.println(F("setLedStatus failed"));
  }
}

void test1()
{
  for (uint8_t j = 0; 4 > j; j++) {
    for (uint8_t l = 0; LED_COUNT > l; l++) {
      for (uint8_t s = 0; LED_STATE_COUNT > s; s++) {
        setled(l, states[s]);
        delay(20);
      }
    }
  }
}

void test2()
{
  for (uint8_t s = 0; LED_STATE_COUNT > s; s++) {
    for (uint8_t l = 0; LED_COUNT > l; l++) {
      setled(l, states[s]);
      delay(400);
    }
  }
}

void test3()
{
  for (int i = 0; 1000 > i; i++) {
    uint8_t l = random(0, LED_COUNT);
    ledStatus s = (ledStatus)random(0, LED_STATE_COUNT);
    setled(l, states[s]);
    delay(40);
  }
}

void loop() 
{
  Serial.println(F("\nTest 1"));
  test1();
  delay(1000);

  Serial.println(F("Test 2"));
  test2();
  delay(1000);

  Serial.println(F("Test 3"));
  test3();
  delay(1000);
}

Library header file:

#ifndef BOARD_16X_DUAL_LED_H_INCLUDED
#define BOARD_16X_DUAL_LED_H_INCLUDED

#include <Adafruit_MCP23017.h>

#define LED_STATE_COUNT 4
#define LED_COUNT 16

enum ledStatus {
  LedOff = 0,
  LedRed,
  LedGreen,
  LedBoth,
};

class Board_16x_dual_led
{
  private:
    Adafruit_MCP23017 m_ctrl[2];
    uint8_t           m_adr[2];
    ledStatus         m_ledStatus[LED_COUNT];

  public:
    Board_16x_dual_led(const uint8_t adr1, const uint8_t adr2);
    ~Board_16x_dual_led();
    
    bool setup();
    bool setLedStatus(const uint8_t ledno, const ledStatus state, const bool save = true);
    ledStatus getStatus(const uint8_t ledno);
    void restore();
};

#endif

And library .cpp file:

#include "Arduino.h" 
#include "Board_16x_dual_led.h"

Board_16x_dual_led::Board_16x_dual_led(const uint8_t adr1, const uint8_t adr2)
{
  m_adr[0] = adr1;
  m_adr[1] = adr2;
}

Board_16x_dual_led::~Board_16x_dual_led()
{
}

bool Board_16x_dual_led::setup()
{
  m_ctrl[0].begin(m_adr[0] - 0x20);
  m_ctrl[1].begin(m_adr[1] - 0x20);
  
  for (uint8_t i = 0; LED_COUNT > i; i++) {
    m_ctrl[0].pinMode(i, OUTPUT);
    m_ctrl[1].pinMode(i, OUTPUT);
  }
  
  for (uint8_t i = 0; LED_COUNT > i; i++) {
    if (!setLedStatus(i, LedOff, true)) {
      return false;
    }
  }
  
  return true;
}

bool Board_16x_dual_led::setLedStatus(const uint8_t ledno, const ledStatus state, const bool save)
{
  if (LED_COUNT > ledno) {
    uint8_t unit = ledno / 8;
    uint8_t port = 2 * (ledno % 8);
    
#if BOARD_16X_DUAL_LED_DBG == 1
    Serial.print(F("unit="));
    Serial.print(unit);
    Serial.print(F(", port="));
    Serial.println(port);
#endif
    
    if ((0 == unit || 1 == unit) && (0 <= port && 15 > port)) {
      switch (state) {
        case LedOff:
          m_ctrl[unit].digitalWrite(port, LOW);
          m_ctrl[unit].digitalWrite(port + 1, LOW);
          break;

        case LedRed:
          m_ctrl[unit].digitalWrite(port, HIGH);
          m_ctrl[unit].digitalWrite(port + 1, LOW);
          break;

        case LedGreen:
          m_ctrl[unit].digitalWrite(port, LOW);
          m_ctrl[unit].digitalWrite(port + 1, HIGH);
          break;

        case LedBoth:
          m_ctrl[unit].digitalWrite(port, HIGH);
          m_ctrl[unit].digitalWrite(port + 1, HIGH);
          break;
      }
      
      if (save) {
        m_ledStatus[ledno] = state;
      }
      
      return true;
    }
  }
  
  return false;
}

ledStatus Board_16x_dual_led::getStatus(const uint8_t ledno)
{
  if (0 <= ledno && LED_COUNT > ledno) {
    return m_ledStatus[ledno];
  }
  
  return LedOff;
}

void Board_16x_dual_led::restore()
{
  for (uint8_t i = 0; LED_COUNT > i; i++) {
    setLedStatus(i, m_ledStatus[i], false);
  }
}

When running the sketch it fails in test2. It seems to be the first MCP23017 that behave strange. The LED sequence for this is:

 0   1   2   3   4   5   6   7
Off Off Off Off Off Off Off Off
Red Off Off Off Off Off Off Off
Red Red Off Off Off Off Off Off
Red Red Red Off Off Off Off Off
Red Red Red Off Off Off Off Off
Red Red Red Red Off Off Off Off
Red Red Red Red Red Off Off Off
Red Red Red Red Red Red Off Off
Red Red Red Red Red Red Red Off
Red Red Red Red Red Red Red Red
Grn Red Red Red Red Red Red Red
Grn Grn Red Red Red Red Red Red
Grn Grn Grn Red Red Red Red Red 
Grn Grn Grn Grn Red Red Red Red 
Grn Grn Grn Grn Grn Red Red Red 
Grn Grn Grn Grn Grn Grn Red Red 
Grn Grn Grn Grn Grn Grn Grn Red 
Grn Grn Grn Grn Grn Grn Grn Grn
RG  Grn Grn Grn Grn Grn Grn Grn 
RG  RG  Grn Grn Grn Grn Grn Grn
RG  RG  RG  Grn Grn Grn Grn Grn 
RG  RG  RG  RG  Grn Grn Grn Grn 
RG  RG  RG  RG  RG  Grn Grn Grn  
RG  RG  RG  RG  RG  RG  Grn Grn 
RG  RG  RG  RG  RG  RG  RG  Grn 
Off Grn Off Red Off Off Off Grn <---- ERROR

The other one behave OK.

thehardwareman:
When running the sketch it fails in test2. It seems to be the first MCP23017 that behave strange.

Test the chips by swapping their positions. If you see the same behavior then it's not a hardware problem.

Sorry, but I do know understand what you mean by "What is yours?".

What is your circuit?
How have you wired it up?
Please post a schematic so we can see if it is correct.
Then please post a photograph to see if you have implemented it correctly.

I will replace the chip I suspect is bad when I get back home (currently at my cottage). Also post a picture and schematic.

It was the chip. Replaced it and now it works as expected.

So mark the first post title as "Solved". Even better, "Solved! Bad chip". :grinning: