MCP23017 and Led Matrix Display delay problem

And if I will get another 'boot in the face' like yesterday? In the middle of the discussion?

Go on think about it. The 8x8 matrix is either arranged as 8 horizontal bytes or as 8 vertical bytes. Most likely 8 vertical bytes.

To multiplex the display you:
write the vertical byte to 8 pins. And write one "enable" bit to the other 8 pins. i.e. to address the a particular vertical column.

Rinse and repeat for each of the 8 vertical bytes. e.g. pausing for approx 3ms on each column.

e.g. using

 	 * For portA and portB variable to effectively match the desired port,
	 * you have to supply a portA register address to reg. Otherwise, values
	 * will be reversed due to the way the MCP23017 works in Byte mode.
	 */
	void writeRegister(MCP23017Register reg, uint8_t portA, uint8_t portB);

Which means you would just do something like

for (i = 0; i < 8; i++) {
    mcp1.writeRegister(0x14, bytedata[i], 1 << i);
    delay(1);
}

I bet that this involves 8 sets of 4 I2C bytes. i.e. about 3ms to draw one Frame @ 100kHz plus a 1ms delay to give 4ms per column

Untested. But it looks pretty simple to me.

David.

1 Like

A short movie with a bit better code for Adafruit MCP23017 library that I originally come with in the beginning and I have some relatively good results from it. But not entirely satisfied. I will try your other suggestions and see how it will be. I will also post my progress with the second library made by a german guy " blemasle MCP23017 Library" that @guix suggested, but im afraid this is incomplete because some parts I figure it out, some parts are not figured , so its incomplete.
Thank you.

Your scan is horizontal byte with one row "enabled" at a time. i.e. my vertical byte was a wrong guess !

I can't watch your shaky video. It makes my head hurt.

It does not matter which MCP23017 library you use. You still just write an 8-pixel byte with the corresponding "row-enable bit".

Paste the actual code. i.e. something stationary that we can actually read.
Say which library you are using e.g. GitHub link.
It is wise to test with known patterns e.g. an F and a 4

Oh, and I can't tell whether you have any resistors or not.

David.

1 Like

7 resistors per each side so a total of 14 @ 1k each. I single led is litting bright enough.

yes...
the output for this 3LEDsDiagonal_B code worked excellent.
using Adafruit_MCP23X17 library.

//code name: mcp23017_LMD3_3LEDsDiagonal_B
#include "Arduino.h"                    //core library that contains all of the Arduino’s built-in functions (from 2022)
#include <Adafruit_MCP23X17.h>          //this is Adafruit-MCP23017-Arduino-Library version 2.1.0

 
Adafruit_MCP23X17 mcp1; //Instantiate mcp1 object
 
void setup()
{
  Serial.begin(19200);
  mcp1.begin_I2C(0x20);
  for(int i = 0; i <= 15; i++) 
  {
    mcp1.pinMode(i, INPUT);
  }

int dly = 2;
void drawDiagonal()
{
  //line1
 mcp1.pinMode(6, OUTPUT);   //line
 mcp1.pinMode(10, OUTPUT);   //column
 mcp1.digitalWrite(6, HIGH);
 mcp1.digitalWrite(10, LOW);
 delay(dly);
//Reset
 mcp1.pinMode(6, INPUT);
 mcp1.pinMode(10, INPUT);

  //line2
 mcp1.pinMode(2, OUTPUT);   //line
 mcp1.pinMode(3, OUTPUT);   //column
 mcp1.digitalWrite(2, HIGH);
 mcp1.digitalWrite(3, LOW);
 delay(dly);
//Reset
 mcp1.pinMode(2, INPUT);
 mcp1.pinMode(3, INPUT);

   //line3
 mcp1.pinMode(8, OUTPUT);   //line
 mcp1.pinMode(4, OUTPUT);   //column
 mcp1.digitalWrite(8, HIGH);
 mcp1.digitalWrite(4, LOW);
 delay(dly);
//Reset
 mcp1.pinMode(8, INPUT);
 mcp1.pinMode(4, INPUT);
}



void loop()
{
 drawDiagonal();
}

and here is the updated "ch A" code, that is doing better than before
using Adafruit_MCP23X17 library. But still not good enough.

//code name: mcp23017_LMD3_ABC123_B - (chA)
#include "Arduino.h"                    //core library that contains all of the Arduino’s built-in functions (from 2022)
#include <Adafruit_MCP23X17.h>          //this is Adafruit-MCP23017-Arduino-Library version 2.1.0
 
Adafruit_MCP23X17 mcp1; //Instantiate mcp1 object
 
void setup()
{
  Serial.begin(19200);
  mcp1.begin_I2C(0x20);
  for(int i = 0; i <= 15; i++) 
  {
    mcp1.pinMode(i, INPUT);
  }
  for(int i = 0; i <=15; i++) 
  {
    mcp1.digitalWrite(i, LOW);
  }
}


int dly = 1;
void chr_A()
{
  //line1
 mcp1.pinMode(5, OUTPUT);   //line
 mcp1.pinMode(10, OUTPUT);  //column
 mcp1.pinMode(3, OUTPUT);   //column
 mcp1.pinMode(4, OUTPUT);   //column
 mcp1.digitalWrite(5, HIGH);
 mcp1.digitalWrite(10, LOW);
 mcp1.digitalWrite(3, LOW);
 mcp1.digitalWrite(4, LOW);
 delay(dly);
//Reset
 mcp1.pinMode(5, INPUT);   //line
 mcp1.pinMode(10, INPUT);  //column
 mcp1.pinMode(3, INPUT);   //column
 mcp1.pinMode(4, INPUT);   //column

 
  //line2
 mcp1.pinMode(0, OUTPUT);   //line
 mcp1.pinMode(1, OUTPUT);   //column
 mcp1.pinMode(13, OUTPUT);  //column
 mcp1.digitalWrite(0, HIGH);
 mcp1.digitalWrite(1, LOW);
 mcp1.digitalWrite(13, LOW);
 delay(dly);
//Reset
 mcp1.pinMode(0, INPUT);   //line
 mcp1.pinMode(1, INPUT);   //column
 mcp1.pinMode(13, INPUT);  //column


  //line3
 mcp1.pinMode(6, OUTPUT);   //line
 mcp1.pinMode(1, OUTPUT);   //column
 mcp1.pinMode(13, OUTPUT);  //column
 mcp1.digitalWrite(6, HIGH);
 mcp1.digitalWrite(1, LOW);
 mcp1.digitalWrite(13, LOW);
 delay(dly);
//Reset
 mcp1.pinMode(6, INPUT);   //line
 mcp1.pinMode(1, INPUT);   //column
 mcp1.pinMode(13, INPUT);  //column

  //line4-midle
 
 mcp1.pinMode(2, OUTPUT);   //line
 mcp1.pinMode(1, OUTPUT);   //column
 mcp1.pinMode(10, OUTPUT);  //column
 mcp1.pinMode(3, OUTPUT);   //column
 mcp1.pinMode(4, OUTPUT);   //column
 mcp1.pinMode(13, OUTPUT);  //column
 mcp1.digitalWrite(2, HIGH);
 mcp1.digitalWrite(1, LOW);
 mcp1.digitalWrite(10, LOW);
 mcp1.digitalWrite(3, LOW);
 mcp1.digitalWrite(4, LOW);
 mcp1.digitalWrite(13, LOW);
 delay(dly);
//Reset
 mcp1.pinMode(2, INPUT);   //line
 mcp1.pinMode(1, INPUT);   //column
 mcp1.pinMode(10, INPUT);  //column
 mcp1.pinMode(3, INPUT);   //column
 mcp1.pinMode(4, INPUT);   //column
 mcp1.pinMode(13, INPUT);  //column
 

  //line5
 mcp1.pinMode(8, OUTPUT);   //line
 mcp1.pinMode(1, OUTPUT);   //column
 mcp1.pinMode(13, OUTPUT);  //column
 mcp1.digitalWrite(8, HIGH);
 mcp1.digitalWrite(1, LOW);
 mcp1.digitalWrite(13, LOW);
 delay(dly);
//Reset
 mcp1.pinMode(8, INPUT);   //line
 mcp1.pinMode(1, INPUT);   //column
 mcp1.pinMode(13, INPUT);  //column


  //line6
 mcp1.pinMode(14, OUTPUT);   //line
 mcp1.pinMode(1, OUTPUT);    //column
 mcp1.pinMode(13, OUTPUT);   //column
 mcp1.digitalWrite(14, HIGH);
 mcp1.digitalWrite(1, LOW);
 mcp1.digitalWrite(13, LOW);
 delay(dly);
//Reset
 mcp1.pinMode(14, INPUT);   //line
 mcp1.pinMode(1, INPUT);    //column
 mcp1.pinMode(13, INPUT);   //column


  //line7
 mcp1.pinMode(9, OUTPUT);   //line
 mcp1.pinMode(1, OUTPUT);   //column
 mcp1.pinMode(13, OUTPUT);  //column
 mcp1.digitalWrite(9, HIGH);
 mcp1.digitalWrite(1, LOW);
 mcp1.digitalWrite(13, LOW);
 delay(dly);
//Reset
 mcp1.pinMode(9, INPUT);   //line
 mcp1.pinMode(1, INPUT);   //column
 mcp1.pinMode(13, INPUT);  //column
 
}



void loop()
{
 chr_A();
}

and next... I will post some code I did using the german library that is incomplete at the moment.... with very big issues to resolve.

So... the german 'blemasle MCP23017 Library'
I stay all night and all day to figure out how this thing actually may drive this led matrix. Here is the results I come with:
It is not the same as adafruit !!! its more complicated.... and it appears it is not a finished library because there are some issues I can not get over.
the summary is this:

/*
Logic v1
//Lines
// mcp1.writeRegister(MCP23017Register::GPIO_A, 0b00100000); //line1   (all to Low but 1 to High)
// mcp1.writeRegister(MCP23017Register::GPIO_A, 0b00000001); //line2
// mcp1.writeRegister(MCP23017Register::GPIO_A, 0b01000000); //line3
// mcp1.writeRegister(MCP23017Register::GPIO_A, 0b00000100); //line4
// mcp1.writeRegister(MCP23017Register::GPIO_B, 0b00010000); //line4
// mcp1.writeRegister(MCP23017Register::GPIO_B, 0b00000001); //line5
// mcp1.writeRegister(MCP23017Register::GPIO_B, 0b01000000); //line6
// mcp1.writeRegister(MCP23017Register::GPIO_B, 0b00000010); //line7
//Columns version1
// mcp1.writeRegister(MCP23017Register::GPIO_A, 0b11111101); //column1 (all to High but 1 to Low)
// mcp1.writeRegister(MCP23017Register::GPIO_B, 0b11111011); //column2
// mcp1.writeRegister(MCP23017Register::GPIO_A, 0b11110111); //column3
// mcp1.writeRegister(MCP23017Register::GPIO_A, 0b11101111); //column4
// mcp1.writeRegister(MCP23017Register::GPIO_B, 0b11011111); //column5
*/

Trust me, I tried every permutation possible and ONLY this one worked. As you can clearly see, if you have 0b00100000 on portA for the line1, you MUST have 0b11111101 on the same portA for the column to be activated.
This was the major problem I stumble upon and that eat all night and all the energy to figure this little detail I am showing right now. Its an absurdity.
BUT... for the other pins or connections, it worked just fine, I could open specific single leds, specific lines and columns. But not all of them when it involved the same portA In and Out. I strongly believe this library is incomplete for X reasons.
I also tried some other functions from its library header and cpp file. For that, you must inspect the code and see what I tested. Most of the code is commented out because I keep the good results I got to a point. And then I tried the next possibility and so on.
Here are 2 codes which contain a lot of trying - again, some leds/lines/col worked, some didnt. All I did there was to find the motive for the ones it failed.

Right here, Im using 'blemasle MCP23017 Library'
program name: mcp23017_LinesAndColumns

#include "Arduino.h"   //core library that contains all of the Arduino�s built-in functions (from 2022)
#include <Wire.h>
#include <MCP23017.h>

MCP23017 mcp1 = MCP23017(0x20);

void setup() {
    Wire.begin();
    Serial.begin(19200);
    mcp1.init();


    //0b11111111 = output
    //0b00000000 = input
//      mcp1.portMode(MCP23017Port::A, 0b11111111, 0x00);  //PortA as Input Low
//      mcp1.portMode(MCP23017Port::B, 0b11111111, 0x00);  //PortB as Input Low
//      mcp1.portMode(MCP23017Port::A, 0b00000000);  //PortA as Output
//      mcp1.portMode(MCP23017Port::B, 0b00000000);  //PortB as Output
//      mcp1.writeRegister(MCP23017Register::GPIO_A, 0b00000000); //PortA to Low
//      mcp1.writeRegister(MCP23017Register::GPIO_B, 0b00000000); //PortB to Low

//Lines
// mcp1.writeRegister(MCP23017Register::GPIO_A, 0b00100000); //line1 
// mcp1.writeRegister(MCP23017Register::GPIO_A, 0b00000001); //line2
// mcp1.writeRegister(MCP23017Register::GPIO_A, 0b01000000); //line3
// mcp1.writeRegister(MCP23017Register::GPIO_A, 0b00000100); //line4  libere 1,4,5,7
// mcp1.writeRegister(MCP23017Register::GPIO_B, 0b00010000); //line4
// mcp1.writeRegister(MCP23017Register::GPIO_B, 0b00000001); //line5
// mcp1.writeRegister(MCP23017Register::GPIO_B, 0b01000000); //line6
// mcp1.writeRegister(MCP23017Register::GPIO_B, 0b00000010); //line7
//Columns version1
// mcp1.writeRegister(MCP23017Register::GPIO_A, 0b11111101); //column1
// mcp1.writeRegister(MCP23017Register::GPIO_B, 0b11111011); //column2
// mcp1.writeRegister(MCP23017Register::GPIO_A, 0b11110111); //column3
// mcp1.writeRegister(MCP23017Register::GPIO_A, 0b11101111); //column4
// mcp1.writeRegister(MCP23017Register::GPIO_B, 0b11011111); //column5

   
/*
    //first column (with 6th led off)
    mcp1.portMode(MCP23017Port::A, 0b11111111, 0x00);  //PortA as Input Low
    mcp1.portMode(MCP23017Port::B, 0b11111111, 0x00);  //PortB as Input Low
    mcp1.portMode(MCP23017Port::A, 0b00000000, 0x00);   //PortA as Output
    mcp1.writeRegister(MCP23017Register::GPIO_A, 0b11101111); //line
    mcp1.portMode(MCP23017Port::B, 0b00000000, 0x00);   //PortB as Output
    mcp1.writeRegister(MCP23017Register::GPIO_B, 0b10111111); //column
*/

    //first column FULL
    //mcp1.portMode(MCP23017Port::A, 0b11111111, 0x00);  //PortA as Input Low
    //mcp1.portMode(MCP23017Port::B, 0b11111111, 0x00);  //PortB as Input Low
    mcp1.portMode(MCP23017Port::A, 0b00000000, 0x00);   //PortA as Output
    mcp1.writeRegister(MCP23017Register::GPIO_A, 0b11111111); //column
    mcp1.portMode(MCP23017Port::B, 0b00000000, 0x00);   //PortB as Output
    mcp1.writeRegister(MCP23017Register::GPIO_B, 0b11111011); //column

    
}



int dly = 10;
void loop() 
{
     /* 
      mcp1.writeRegister(MCP23017Register::GPIO_B, 0b00000001);
      delay(dly);
      mcp1.writeRegister(MCP23017Register::GPIO_A, 0b00000000);
      delay(dly);
      */
}

and the second one:
program name: mcp23017_LMD2_SingleB

#include "Arduino.h"                    //core library that contains all of the Arduino�s built-in functions (from 2022)
#include <Wire.h>
#include <MCP23017.h>

MCP23017 mcp1 = MCP23017(0x20);

void setup() {
    Wire.begin();
    Serial.begin(19200);
    mcp1.init();


    //0b11111111 = output
    //0b00000000 = input
     mcp1.portMode(MCP23017Port::A, 0b11111111, 0x00);  //PortA as INPUT Low
     mcp1.portMode(MCP23017Port::B, 0b11111111, 0x00);  //PortB as INPUT Low
    // mcp1.portMode(MCP23017Port::A, 0b00000000);  //PortA as OUTPUT
    // mcp1.portMode(MCP23017Port::B, 0b00000000);  //PortB as OUTPUT
    // mcp1.writeRegister(MCP23017Register::GPIO_A, 0b00000000); //PortA to Low
    // mcp1.writeRegister(MCP23017Register::GPIO_B, 0b00000000); //PortB to Low

/*
Logic v1
//Lines
// mcp1.writeRegister(MCP23017Register::GPIO_A, 0b00100000); //line1   (all to Low but 1 to High)
// mcp1.writeRegister(MCP23017Register::GPIO_A, 0b00000001); //line2
// mcp1.writeRegister(MCP23017Register::GPIO_A, 0b01000000); //line3
// mcp1.writeRegister(MCP23017Register::GPIO_A, 0b00000100); //line4
// mcp1.writeRegister(MCP23017Register::GPIO_B, 0b00010000); //line4
// mcp1.writeRegister(MCP23017Register::GPIO_B, 0b00000001); //line5
// mcp1.writeRegister(MCP23017Register::GPIO_B, 0b01000000); //line6
// mcp1.writeRegister(MCP23017Register::GPIO_B, 0b00000010); //line7
//Columns version1
// mcp1.writeRegister(MCP23017Register::GPIO_A, 0b11111101); //column1 (all to High but 1 to Low)
// mcp1.writeRegister(MCP23017Register::GPIO_B, 0b11111011); //column2
// mcp1.writeRegister(MCP23017Register::GPIO_A, 0b11110111); //column3
// mcp1.writeRegister(MCP23017Register::GPIO_A, 0b11101111); //column4
// mcp1.writeRegister(MCP23017Register::GPIO_B, 0b11011111); //column5
*/

 // BIGproblem: when in the same PortA is the Line and the Column, 
 // either 2 leds are opening at once,not 1; either a specific LED is not litting at all. 
 //     mcp1.portMode(MCP23017Port::A, 0b11011101);         //line1
 //     mcp1.writeRegister(MCP23017Register::GPIO_A, 0b11111101);
 
/*
Version 2
//Lines
// mcp1.portMode(MCP23017Port::A, 0b11011111, 0x00);         //line1
*/

/*
    //The first single LED !
    mcp1.portMode(MCP23017Port::A, 0b11011111, 0x00);         //line1
    mcp1.writeRegister(MCP23017Register::GPIO_A, 0b11111111); 
//0000-
//00000
//00000
//00000
//00000
//00000
//00000

    mcp1.portMode(MCP23017Port::A, 0b11111110, 0x00);         //line2
    mcp1.writeRegister(MCP23017Register::GPIO_A, 0b11011111); 
//00000
//0000-
//00000
//00000
//00000
//00000
//00000

//    mcp1.portMode(MCP23017Port::A, 0b10111111, 0x00);         //line1
//    mcp1.writeRegister(MCP23017Register::GPIO_A, 0b11111111);
//00000
//00000
//0000-
//00000
//00000
//00000
//00000

      mcp1.portMode(MCP23017Port::A, 0b11011111);         //line1
      mcp1.writeRegister(MCP23017Register::GPIO_A, 0b11111111);
      mcp1.portMode(MCP23017Port::B, 0b11111011);         //column2
      mcp1.writeRegister(MCP23017Register::GPIO_B, 0b00000000); 
//0-000
//00000
//00000
//00000
//00000
//00000
//00000
*/


   //,false ,true

   // led ON at A1
   //  mcp1.pinMode(05,1);  //line1
   //  mcp1.pinMode(01,1); //column1


   // led ON at E2
   // mcp1.pinMode(0,1);  //
   // mcp1.pinMode(13,1); //column5
   
   // led ON at E3
   // mcp1.pinMode(6,1);  //
   // mcp1.pinMode(13,1); //column5
   
   // led ON at E4
   // mcp1.pinMode(2,1);  //
   // mcp1.pinMode(13,1); //column5


   mcp1.pinMode(5,1);  //line1
   mcp1.pinMode(0,1);  //line2
   mcp1.pinMode(6,1);  //line3
   mcp1.pinMode(2,1);  //line4
   mcp1.pinMode(8,1);  //line5
   mcp1.pinMode(14,1);//line6
   mcp1.pinMode(9,1);  //line7
      
   mcp1.pinMode(1,1); //column1
   mcp1.pinMode(10,1);//column2
   mcp1.pinMode(3,1); //column3
   mcp1.pinMode(4,1); //column4
   mcp1.pinMode(13,1); //column5

   mcp1.pinMode(12,0);

    
}


int dly = 10;
void loop() 
{
     
}

-------Thank you-------

Thanks for posting the code.
Thanks for clarifying the resistors.

Quite honestly you could drive your matrix directly from an AVR with such high resistors.
e.g. all pixels on for each row. means 8 pixels lit via 1k0 series and the common limited by 1k0 too!!
i.e. 312uA max per data bit, 2.5mA for a single common pin.

The MCP23017 can source and sink 25mA per pin. 125mA total.

I am happy to help with software or hardware. I give up when it requires both.

Seriously, you can buy an MAX7219 from a local Ebay supplier. You can get a 32x8 for about 8 Euros.

David.

1 Like

Thank you. I am actually taking in consideration everything I get from anyone ! No exceptions. But it takes time to concentrate on everything. Until now I concentrated on literally hammering those libraries and the code to make something to fraking blink. And very slowly but surely I push it. Here is what I could push up in my presentation so far.
I will take in consideration everything everyone here suggested. But in time, a bit more slower and with research and strategic. I will update on every aspect of everything.
Someone else asked me the same question in a private message (that I can not find the option anywhere available for new guys like me - great welcome btw - yah, american way - haha) and my answer was that I can not jump to other chips and that I stay with this MCP23017 for multiple reasons:

  • I have 8 of them already
  • the cost was relatively expensive for my pockets
  • I built a board with 8 of them, manually and it was hard and slow to make as the proverbial F-u-c
  • I am testing this board to its limits and this LED Matrix Display is a perfect 'test' project.
  • I am testing arduino boards actually in the same time, since as I mentioned already, I am quite new to arduino. I have a general idea but when in details, im not that experienced. So now with this project I am testing this side as well.
  • I am not a good programmer in arduino medium/IDE since I am also new to this as well. Learning it as I go. I really appreciate all the help I can get from the code side of things so far !!!! Seriously, I see some very interesting code ideas so far and I like it.
  • in the end I will consider other chips, but for the moment this MCP board will do just fine.
    I like diversity and you guys give me plenty, which is VERY good. I like you already. Except the 'boot in the Face' thing that probably will repeat soon. I hope not. Haha. This one:

Heh, not much left to do.
I tested both your good suggestions: the writeGPIO and delay(dly);

I looked everywhere and I couldnt find your writeGPIOA or writeGPIOB functions. But I did find in Adafruit library this resembling method, where you have to pass the port number as 0 for portA or 1 for portB as those instructions say.

/*!
  @brief Bulk write all pins on a port.
  @param value pin states to write as a uint8_t.
  @param port 0 for Port A, 1 for Port B (MCP23X17 only).
*/
/**************************************************************************/
void Adafruit_MCP23XXX::writeGPIO(uint8_t value, uint8_t port) {
  Adafruit_BusIO_Register GPIO(i2c_dev, spi_dev, MCP23XXX_SPIREG,
                               getRegister(MCP23XXX_GPIO, port));
  GPIO.write(value);
}

I test it like this:

  //line2
 mcp1.pinMode(2, OUTPUT);   //line
 mcp1.pinMode(3, OUTPUT);   //column
// mcp1.digitalWrite(2, HIGH);
// mcp1.digitalWrite(3, LOW);
 mcp1.writeGPIO(0b00100000,0);
// delay(dly);
//Reset
 mcp1.pinMode(2, INPUT);
 mcp1.pinMode(3, INPUT);

but it didnt work. I choose this line2 to test because both pins are in portA, 2 and 3 as you can see in the commented code. I tried all the permutations I could think of but nothing really worked. Shame.
In the same code here I commented out the delay(dly), also I took it out from all my recent codes and it was like I said, no difference between the dly=1 or no delay at all. But it is a very good point that I fly over it. Now it remained with all the delays commented out. Just saying, that the minimum value of a delay is very close to a 'no' delay especially when the memory is plenty. I know exactly the fight for space and for cycles, when doing assembler for a PIC.
Ive also looked on both MAX7219 and HT16K33 and they look very interesting and very cheap indeed. They will remain for the future as a curiosity to have. I never worked with them. But for now, as I mentioned already, this project is in fact driving this led matrix from this MCP board through arduino. To be clear. :wink: Thank you.

they are in the separate MXP23X17 files and just call the writeGPIO with the second parameter 0 or 1:

regarding port access ... take care of MSB in binary.

// mcp1.digitalWrite(2, HIGH);
// mcp1.digitalWrite(3, LOW);
 mcp1.writeGPIO(0b0000100,0); // MSB ... from 7 left to 0 right
1 Like

Thank you mister @noiasca !
Indeed I was looking in the wrong files, for the Adafruit_MCP23XXX.h and Adafruit_MCP23XXX.cpp which in my mind at that time was the base on which MXP23X17 are built on. Now I checked more carefully and opened your MXP23X17.cpp (also you linked it as well but I checked it anyway to understand where was the mistake) and you are perfectly right, this writeGPIOA function really exist, and I also confirm it is now working fine, thanks to your very good observation about that //MSB comment -MostSignificantBit- that I completely forget. Daem.... I really dont work with these things everyday like you guys, so I forget stuff but I remember quickly if shown the right direction.
-Excelent so far and Im very happy you demistify this little detail for me !!!
Here are my working code lines, both tested and working now:

  //line2
 mcp1.pinMode(2, OUTPUT);   //line
 mcp1.pinMode(3, OUTPUT);   //column
 mcp1.digitalWrite(2, HIGH);
 mcp1.digitalWrite(3, LOW);
 
 mcp1.writeGPIO(0b0000100,0); //MSB ... from 7 left to 0 right
 mcp1.writeGPIOA(0b0000100);

Ok then, I will try harder to optimize this code using this last working function. I will update you soon with the results.
BTW, in my last code optimization, commenting out the delay() function and changing the Reset loop with individual 'switch to Input' for each specific pin, did improve quite well the final result in the Led Matrix Display refresh rate. At this point, the 3ledsDiagonal test program worked absolutly perfectly, but still not good enough for a bigger character/shape that has multiple LEDs to drive.
I trust we will get there.
From my tests I did with that german 'blemasle library', it performed much more faster than Adafruit library. But it's downside it is having serious issues with the same port IO, where one pin must be High and the rest Low, and then the second pin to be Low and the rest High. So its an impossibility. Also it's not having a working 'floating' pin option, not high-not low to successfully drive the same port. The 'floating' option I do in Adafruit is to turn to Input everything. But in blemasle library, it's Input is either Low or High, and really doesnt matter if its Input or Output, it will be either High or Low, but not inbetween like Adafruit library managed to solve this problem. I hope is clear enough how I see it. This is the best explanation of what it's problem was that I find. Oh man, you have no idea how much I hammered that library and how many tests I did (houndreds) until I reach this final conclusion.
But now...... with this writeGPIO(A/B) last function that is adressing multiple pins at once - the entire port at once-, I believe it is more closer to the german blemasle library with this functionality, and as someone here I believe already mentioned, it will speed up the comunication this way. I will definitely try it and communicate the results.
Thank you - you were a great help !

depending on the wiring (i.e. one port for anodes, one port for cathodes) you should be able to do a full cycle (i.e. a full column) with just two I2C writes.

furthermore - and this was meant with my "step 4" in Post #19 - you can write your own low level hardware interface and use the 16 bit serial mode of the MCP and send two bytes to the MCP with one I2C write.

But as mentioned with step 5 ... on long term I'm convinced that the MCP23x17 is just not the best alternative for multiplexing a LED matrix.

1 Like

Likewise using Shift Registers or regular PORTs. You need a regular Timer interrupt to give a fair share of current to each row. Otherwise you are left with a stopped multiplex pumping 8x current that the stationary row was expecting.

A MAX7219 looks after the multiplexing. And looks after the average current too.

David.

1 Like

Related to what you just mentioned.... I read it now after I find and tested the code. I made a new file named "mcp23017_LMD3_ABC123_C" and use only writeGPIOA or writeGPIOB in it.

  • for example:
  //line3
 mcp1.pinMode(6, OUTPUT);   //line
 mcp1.pinMode(1, OUTPUT);   //column
 mcp1.pinMode(13, OUTPUT);  //column
 mcp1.digitalWrite(13, LOW);
// mcp1.digitalWrite(6, HIGH);
// mcp1.digitalWrite(1, LOW);
 mcp1.writeGPIOA(0b01000000);
 delay(dly);
//Reset
 mcp1.pinMode(6, INPUT);   //line
 mcp1.pinMode(1, INPUT);   //column
 mcp1.pinMode(13, INPUT);  //column

and this worked a bit more faster than previeous. Which was good. Ive also noticed the brightness of the leds are diminishing with the high frequency as well.
-And then, I looked more closely into Adafruit library and it catch my eye another function that writes to both AB ports at once. Ohohoooo - I said and I test it , it worked and I write this secondary code named "mcp23017_LMD3_ABC123_D" that is using this new function:

  • for example: (the same line3)
  //line3
 mcp1.pinMode(6, OUTPUT);   //line
 mcp1.pinMode(1, OUTPUT);   //column
 mcp1.pinMode(13, OUTPUT);  //column
// mcp1.digitalWrite(13, LOW);
// mcp1.digitalWrite(6, HIGH);
// mcp1.digitalWrite(1, LOW);
// mcp1.writeGPIOA(0b01000000);
 mcp1.writeGPIOAB(0b0000000001000000);
 delay(dly);
//Reset
 mcp1.pinMode(6, INPUT);   //line
 mcp1.pinMode(1, INPUT);   //column
 mcp1.pinMode(13, INPUT);  //column

And now is even faster than mcp23017_LMD3_ABC123_C code. But STILL not good enough. The flickering is still visible.
We need to push even harder.
If we only are able to write at once all these pinMode to Output and Input !!!!! This is what can further speed up this thing, in my mind.
But is waaay better NOW than when I come with the problem in the first place. Waaaaaay better. Haha. Thank you for that.

Related to what you just saying.... I mentioned already the leds are dimming as long as the fv/speed is increasing. Especially much more lower visibility on a single full line or full column.
-My simple resolve to this was to change those 1.1k resistors into 300R resistors. Which is exactly what I did already and is not full brightness of the led but is a bit more visible than with 1.1k which in daylight was almost invisible, and only in shadow was starting to show its led light. Speaking from the speed of this last program I made last.
Let's make it even faster..... this is the goal here.
-Why arduino is not capable of faster speeds? Why I have to tweak the code so much to squeeze every drop of speed from it? What am I missing? I imagine these high level commands from arduino IDE might in reality write a ton of binary code sent to the CPU of this arduino board. Its the only explanation I can think of.
Thank you !

I suggest that you write your own functions to communicate with the MCP23017 (look how they do in the libraries) exactly like you want, take advantage of its sequencial mode (read the datasheet) to write multiple registers in one i2c transaction (and learn to do bit manipulations, you will need it)

1 Like

Mmmm, the dream, I wish I was that good. Thanks.

I suppose this is it, right? It was a matter of code optimization, proper use of library functions, and the speed right now is either maximum or very close to maximum as this arduino board / procesor can deliver. And the better solution is to use more dedicated IC's like the one you mentioned MAX7219 and HT16K33. Hmmm...it is not as I imagined initially. But what is? right?
-Thank you very much for you kind support and help !!! To everyone.

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