I built an 8x8 led matrix using white 5mm LEDs. I drive the LEDs using the MCP23017 connected to an Arduino over the I2C bus. The wiring of the LEDs in the matrix is such that a row is made up of 8 LEDs whose cathodes are wired together, and a column is made up of 8 LEDs whose anodes are wired together. The end of each row and each column is connected to a GPIO pin of the MCP23017. The size of the pixel is 4cmx4cm which means that a row is 32 cm long (the same for a column).

I cannot get the light to be "stable", it keeps scintillating. I increased the clock frequency of the I2C bus from 100kHz to 400kHz, the light is more stable now, but not enough since the scintillation persists. Before that, I set the I2C clock frequency to 1700kH and the lighting became even slower..., I tried increasing the values of the pullup resistors of the GPIO pins of the MCP23017 to have a quicker response on its GPIO pins, but it had no effects.

enter image description here

I am thinking of 2 potential reasons:

  • The wires are too long for the I2C protocol to handle (a side of the led matrix is 32cm long).
  • the current reaching every column (the anodes) is not enough since there are so many leds to light up.

What do you think is causing this bad lighting? should I change the MCP23017 with another type of expander/protocol?

Here's the code:

#include <Wire.h>
#include <Adafruit_MCP23017.h>

bool four[3][5] = {{1, 1, 1, 0, 0}, {0, 0, 1, 0, 0}, {1, 1, 1, 1, 1}};
Adafruit_MCP23017 mcp;

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

void set_column(uint8_t col_idx, bool pixels[]){

  for(uint8_t i=0; i<8; i++)
    mcp.digitalWrite(i, HIGH);

  for(uint8_t i=8; i<16; i++) //Anodes are connected to Bank B of the MCP23O17
      mcp.digitalWrite(i, LOW);
      mcp.digitalWrite(i, HIGH);

  for(uint8_t i=0; i<8; i++) //Cathodes are connected to Bank A of the MCP23O17
      mcp.digitalWrite(i, LOW);

void display_character(bool character[3][5]){
  bool pixels[8] = {0, 0, 0, 0, 0, 0, 0, 0};
  for(int col=0; col<3; col++){
    for(int i=0; i<5; i++){
      pixels[i+3] = character[col][i];
    set_column(7-col, pixels);

void loop() {
  uint32_t time = millis();
  while(millis() - time < 1000)
  • The problem is that you're using I2C. It's just not fast enough. – Majenko Mar 7 at 20:22
  • 1
    What library are you using? It seems to do one transmission to set one pin. That would result in up to 24 transmissions. Also you write pins 0 to 7 twice, which is unnecessary. Instead it should be possible to write all 16 pins with one transmission. That would be way faster – chrisl Mar 7 at 20:34
  • MAX7219 would be much better driver for 8x8 matrix than bitbandig over extender. And as noted, you should write whole colum at once. However row outputs can drive only about 30mA, so I hope you don't have resistors for the colums too small – KIIV Mar 7 at 21:13
  • 2
    @S.E.K. "Absolute Maximum" sink or source current is 25mA per pin and 150mA for Vss / 125mA Vdd. If the forward voltage of LEDs is about 3V and Vcc for MCP 5V then you have 2V on 20R resistor -> 100mA (theoretically) for a single led. Basically it'll burn soon or later – KIIV Mar 7 at 22:00
  • 1
    Personally I would either use a dedicated LED matrix drive chip, or a dedicated Arduino to drive the display matrix directly. – Majenko Mar 8 at 0:27

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Browse other questions tagged or ask your own question.