mrcodetastic / ESP32-HUB75-MatrixPanel-DMA

An Adafruit GFX Compatible Library for the ESP32, ESP32-S2, ESP32-S3 to drive HUB75 LED matrix panels using DMA for high refresh rates. Supports panel chaining.
MIT License
977 stars 215 forks source link

p4 64x32 1/8 problem. #618

Closed NazarDoeH closed 2 months ago

NazarDoeH commented 7 months ago

Hi, I'm having issues with the 64x32 1/8 matrix. I've tried multiple libraries, but they don't work. This library works somewhat, but not without issues.

https://github.com/mrcodetastic/ESP32-HUB75-MatrixPanel-DMA/assets/57417144/3e49f051-18f6-4b22-b460-cf03fc75d19e

photo_2024-04-16_17-27-38 photo_2024-04-16_17-27-30

define PANEL_RES_X 32 // Number of pixels wide of each INDIVIDUAL panel module.

define PANEL_RES_Y 32 // Number of pixels tall of each INDIVIDUAL panel module.

define NUM_ROWS 1 // Number of rows of chained INDIVIDUAL PANELS

define NUM_COLS 1 // Number of INDIVIDUAL PANELS per ROW

board707 commented 7 months ago

For 1/8 matrix you need to setup the virtual panel with double width and half of height than your real dimensions, So for 64x32 try to setup

#define PANEL_RES_X 128 // Number of pixels wide of each INDIVIDUAL panel module.
#define PANEL_RES_Y 16 // Number of pixels tall of each INDIVIDUAL panel module.
NazarDoeH commented 7 months ago

https://github.com/mrcodetastic/ESP32-HUB75-MatrixPanel-DMA/assets/57417144/50276c68-a81e-4198-8cdc-c77130b46e13

That's for:

define PANEL_RES_X 128 // Number of pixels wide of each INDIVIDUAL panel module.

define PANEL_RES_Y 16 // Number of pixels tall of each INDIVIDUAL panel module.

board707 commented 7 months ago

It looks like you have a problem with connection of one of A B C pin

NazarDoeH commented 7 months ago

https://github.com/mrcodetastic/ESP32-HUB75-MatrixPanel-DMA/assets/57417144/b5bbb8e9-0987-47d0-b70e-fb62be710920

That's connected to the correct pins.

board707 commented 7 months ago

I've tried multiple libraries

Did you work with STM32 or RP2030 boards? Do you ready to test your panel with yet another library?

NazarDoeH commented 7 months ago

I worked with an STM32. But at the moment, I don't have any such boards. All I have are esp32 and esp8266. Also, I have already tried to run on some other libraries, such as PxMatrix, ESP32-P3RGB64x32MatrixPanel, and SmartMatrix.

board707 commented 7 months ago

if you come across a stm32 or rp2040 board, you can try DMD_STM32 library.

mrcodetastic commented 7 months ago

Also, I have already tried to run on some other libraries, such as PxMatrix, ESP32-P3RGB64x32MatrixPanel, and SmartMatrix.

Did it work with these?

board707 commented 7 months ago

The panel has ICDN2037 driver and SM5166 switch - nothing special. It should works with any of these libraries. The issue, probably, is in the multi-line coordinate pattern. Another option - the panel is just broken. However, in the first post we can see a picture with a full panel working - so I think panel is OK

board707 commented 7 months ago

@NazarDoeH Do you ready continue the tests? Could I ask you to run the code?

NazarDoeH commented 7 months ago

Hi @board707. I'm not at home now and won't be back until tomorrow. I'll write to you as soon as I can.

Godwinner1213 commented 5 months ago

Hello everyone, I have a problem with this library. I use four 32x32 1/8 panels, when I chain them into a single row (i.e. NUM_ROWS = 1 and NUM_COLS = 4) everything works perfectly!!! But as soon as I change the chaining configuration to NUM_ROWS = 2 and NUM_COLS =2, only the first row works correctly, the second does not display anything at all as if it were simply disconnected.

board707 commented 5 months ago

It is a known problem, look at the comments to issue #624 To resolve it, you need to edit a VirtualMatrix header file

Godwinner1213 commented 5 months ago

thank you very much @board707, I made the adjustments and everything works

NazarDoeH commented 2 months ago

HII (・ω・)ノ゙. I could display a meaningful image on the matrix; however, I still faced an issue. I hardcoded the pixel position offsets because, as it turns out, the pixel coordinates in my matrix are mixed up with this library. Therefore, I need to write a method that converts normal coordinates to the coordinates corresponding to the actual layout of the matrix (see the screenshot below).

image

My question is: Does this library already have a built-in functionality to handle this?

my code:

#include "ESP32-HUB75-MatrixPanel-I2S-DMA.h"

/* Use the Virtual Display class to re-map co-ordinates such that they draw 
 * correctly on a 32x16 1/8 Scan panel (or chain of such panels).
 */
#include "ESP32-VirtualMatrixPanel-I2S-DMA.h" 

  // Panel configuration
  #define PANEL_RES_X 64 // Number of pixels wide of each INDIVIDUAL panel module. 
  #define PANEL_RES_Y 32 // Number of pixels tall of each INDIVIDUAL panel module.

  #define NUM_ROWS 1 // Number of rows of chained INDIVIDUAL PANELS
  #define NUM_COLS 1 // Number of INDIVIDUAL PANELS per ROW

  // ^^^ NOTE: DEFAULT EXAMPLE SETUP IS FOR A CHAIN OF TWO x 1/8 SCAN PANELS

  // Change this to your needs, for details on VirtualPanel pls read the PDF!
  #define SERPENT true
  #define TOPDOWN false

  // placeholder for the matrix object
  MatrixPanel_I2S_DMA *dma_display = nullptr;

  // placeholder for the virtual display object
  VirtualMatrixPanel  *FourScanPanel = nullptr;

  struct Point2D {
      int16_t x;
      int16_t y;

      Point2D(int xCoord, int yCoord) : x(xCoord), y(yCoord) {}
      Point2D() : x(0), y(0) {}
  };

  Point2D mapper[4][4] = {
      {Point2D{16, 8}, Point2D{0, 8}, Point2D{16, 24}, Point2D{0, 24}},
      {Point2D{48, 8}, Point2D{32, 8}, Point2D{48, 24}, Point2D{32, 24}},
      {Point2D{16, 0}, Point2D{0, 0}, Point2D{16, 16}, Point2D{0, 16}},
      {Point2D{48, 0}, Point2D{32, 0}, Point2D{48, 16}, Point2D{32, 16}}
  };

  /******************************************************************************
   * Setup!
   ******************************************************************************/
  void setup()
  {
    delay(250);

    Serial.begin(115200);
    Serial.println(""); Serial.println(""); Serial.println("");
    Serial.println("*****************************************************");
    Serial.println("*         1/8 Scan Panel Demonstration              *");
    Serial.println("*****************************************************");

/* 
     // 62x32 1/8 Scan Panels don't have a D and E pin!

     HUB75_I2S_CFG::i2s_pins _pins = {
      R1_PIN, G1_PIN, B1_PIN, R2_PIN, G2_PIN, B2_PIN, 
      A_PIN, B_PIN, C_PIN, D_PIN, E_PIN, 
      LAT_PIN, OE_PIN, CLK_PIN
     };
*/
    HUB75_I2S_CFG mxconfig(
                PANEL_RES_X*2,              // DO NOT CHANGE THIS
                PANEL_RES_Y/2,              // DO NOT CHANGE THIS
                NUM_ROWS*NUM_COLS           // DO NOT CHANGE THIS
                //,_pins            // Uncomment to enable custom pins
    );

    mxconfig.clkphase = false; // Change this if you see pixels showing up shifted wrongly by one column the left or right.

    //mxconfig.driver   = HUB75_I2S_CFG::FM6126A;     // in case that we use panels based on FM6126A chip, we can set it here before creating MatrixPanel_I2S_DMA object

    // OK, now we can create our matrix object
    dma_display = new MatrixPanel_I2S_DMA(mxconfig);

    // let's adjust default brightness to about 75%
    dma_display->setBrightness8(96);    // range is 0-255, 0 - 0%, 255 - 100%

    // Allocate memory and start DMA display
    if( not dma_display->begin() )
      Serial.println("****** !KABOOM! I2S memory allocation failed ***********");

    dma_display->clearScreen();
    delay(500);

    // create FourScanPanellay object based on our newly created dma_display object
    FourScanPanel = new VirtualMatrixPanel((*dma_display), NUM_ROWS, NUM_COLS, PANEL_RES_X, PANEL_RES_Y);

    // THE IMPORTANT BIT BELOW!
    FourScanPanel->setPhysicalPanelScanRate(FOUR_SCAN_32PX_HIGH);
  }

  Point2D MapPoint(Point2D point) {
      int yPart = point.y / 8;
      int xPart = point.x / 16;
      return Point2D(point.x % 16 + mapper[xPart][yPart].x, point.y % 8 + mapper[xPart][yPart].y);
  }

  void loop() {
    delay(20);
    for(int x = 0; x < 64; x++)
    {
      for(int y = 0; y < 32; y++)
      {
        Point2D point = MapPoint(Point2D(y, y));
        FourScanPanel->drawPixel(point.x, point.y, dma_display->color565(255, 0, 0)); // red
        point = MapPoint(Point2D(y + 32, y));
        FourScanPanel->drawPixel(point.x, point.y, dma_display->color565(255, 0, 0)); // red
      }
    }
  } // end loop
board707 commented 2 months ago

I don't understand - if you already figured it out, so what you need from the library?

NazarDoeH commented 2 months ago

I figured out what was different in my matrix and how to make it partially work. However, I've only done this for the drawPixel function by providing it with modified coordinates. I still can't use other functions, such as drawLine.

board707 commented 2 months ago

Could you test the panel with code below and show the video? You need to add the pin definitions, of course. (Note: it is not a final solution, just a test)

/*************************************************************************
   Description:

   The underlying implementation of the ESP32-HUB75-MatrixPanel-I2S-DMA only
   supports output to HALF scan panels - which means outputting
   two lines at the same time, 16 or 32 rows apart if a 32px or 64px high panel
   respectively.
   This cannot be changed at the DMA layer as it would require a messy and complex
   rebuild of the library's internals.

   However, it is possible to connect QUARTER (i.e. FOUR lines updated in parallel)
   scan panels to this same library and
   'trick' the output to work correctly on these panels by way of adjusting the
   pixel co-ordinates that are 'sent' to the ESP32-HUB75-MatrixPanel-I2S-DMA
   library.

 **************************************************************************/

/* Use a custom Virtual Display class to re-map co-ordinates such that they draw
   correctly on a Four Scan panel (or chain of such panels).
*/
#include "ESP32-VirtualMatrixPanel-I2S-DMA.h"

/* ================================================== */
// Define custom class derived from VirtualMatrixPanel
class EightPxBasePanel : public VirtualMatrixPanel
{
  public:
    using VirtualMatrixPanel::VirtualMatrixPanel; // inherit VirtualMatrixPanel's constructor(s)

  protected:

    VirtualCoords getCoords(int16_t x, int16_t y);  // custom getCoords() method for specific pixel mapping

};

// define custom getCoords() method for specific pixel mapping
inline VirtualCoords EightPxBasePanel ::getCoords(int16_t x, int16_t y) {

  coords = VirtualMatrixPanel::getCoords(x, y); // first call base class method to update coords for chaining approach

  if ( coords.x == -1 || coords.y == -1 ) { // Co-ordinates go from 0 to X-1 remember! width() and height() are out of range!
    return coords;
  }

 if ((coords.y & 8) == 0)
        {
            coords.x += ((coords.x / panelResX) + 1) * panelResX; // 1st, 3rd 'block' of 8 rows of pixels, offset by panel width in DMA buffer
        }
        else
        {
            coords.x += (coords.x / panelResX) * panelResX; // 2nd, 4th 'block' of 8 rows of pixels, offset by panel width in DMA buffer
        }

        coords.y = (coords.y >> 4) * 8 + (coords.y & 0b00000111);

  return coords;
}
/* ================================================== */
// Panel configuration
#define PANEL_RES_X 64 // Number of pixels wide of each INDIVIDUAL panel module. 
#define PANEL_RES_Y 32 // Number of pixels tall of each INDIVIDUAL panel module.

#define NUM_ROWS 1 // Number of rows of chained INDIVIDUAL PANELS
#define NUM_COLS 2 // Number of INDIVIDUAL PANELS per ROW

// ^^^ NOTE: DEFAULT EXAMPLE SETUP IS FOR A CHAIN OF TWO x 1/8 SCAN PANELS

// Change this to your needs, for details on VirtualPanel pls read the PDF!
#define SERPENT true
#define TOPDOWN false
#define VIRTUAL_MATRIX_CHAIN_TYPE CHAIN_TOP_RIGHT_DOWN

// placeholder for the matrix object
MatrixPanel_I2S_DMA *dma_display = nullptr;

// placeholder for the virtual display object
EightPxBasePanel   *FourScanPanel = nullptr;

/******************************************************************************
   Setup!
 ******************************************************************************/
void setup()
{
  delay(250);

  Serial.begin(115200);
  Serial.println(""); Serial.println(""); Serial.println("");
  Serial.println("*****************************************************");
  Serial.println("*         1/8 Scan Panel Demonstration              *");
  Serial.println("*****************************************************");

  /*
       // 62x32 1/8 Scan Panels don't have a D and E pin!

       HUB75_I2S_CFG::i2s_pins _pins = {
        R1_PIN, G1_PIN, B1_PIN, R2_PIN, G2_PIN, B2_PIN,
        A_PIN, B_PIN, C_PIN, D_PIN, E_PIN,
        LAT_PIN, OE_PIN, CLK_PIN
       };
  */
  HUB75_I2S_CFG mxconfig(
    PANEL_RES_X * 2,            // DO NOT CHANGE THIS
    PANEL_RES_Y / 2,            // DO NOT CHANGE THIS
    NUM_ROWS * NUM_COLS         // DO NOT CHANGE THIS
    //,_pins            // Uncomment to enable custom pins
  );

  mxconfig.clkphase = false; // Change this if you see pixels showing up shifted wrongly by one column the left or right.

  //mxconfig.driver   = HUB75_I2S_CFG::FM6126A;     // in case that we use panels based on FM6126A chip, we can set it here before creating MatrixPanel_I2S_DMA object

  // OK, now we can create our matrix object
  dma_display = new MatrixPanel_I2S_DMA(mxconfig);

  // let's adjust default brightness to about 75%
  dma_display->setBrightness8(40);    // range is 0-255, 0 - 0%, 255 - 100%

  // Allocate memory and start DMA display
  if ( not dma_display->begin() )
    Serial.println("****** !KABOOM! I2S memory allocation failed ***********");

  dma_display->clearScreen();
  delay(500);

  // create FourScanPanellay object based on our newly created dma_display object
  FourScanPanel = new EightPxBasePanel ((*dma_display), NUM_ROWS, NUM_COLS, PANEL_RES_X, PANEL_RES_Y,    VIRTUAL_MATRIX_CHAIN_TYPE);

  // THE IMPORTANT BIT BELOW!
  // FOUR_SCAN_16PX_HIGH
  // FOUR_SCAN_32PX_HIGH
// **** You don't need to set PhysicalPanelScanRate when use your own virtual panel class
 // FourScanPanel->setPhysicalPanelScanRate(FOUR_SCAN_16PX_HIGH);
}

// Test the pixel mapping - fill the panel pixel by pixel
void loop() {

  for (int i = 0; i < FourScanPanel->height(); i++)
  {
    for (int j = 0; j < FourScanPanel->width(); j++)
    {

      FourScanPanel->drawPixel(j, i, FourScanPanel->color565(40, 0, 0));
      delay(20);
    }
  }

  delay(2000);
  dma_display->clearScreen();

} // end loop
NazarDoeH commented 2 months ago

Yep https://github.com/user-attachments/assets/38faed50-15d7-41ef-9c60-e2a41d2e53e7

board707 commented 2 months ago

Thank you Then replace the VirtualCoords function to this:

inline VirtualCoords EightPxBasePanel ::getCoords(int16_t x, int16_t y) {

  coords = VirtualMatrixPanel::getCoords(x, y); // first call base class method to update coords for chaining approach

  if ( coords.x == -1 || coords.y == -1 ) { // Co-ordinates go from 0 to X-1 remember! width() and height() are out of range!
    return coords;
  }

uint8_t pxbase =16;   // pixel base
if ((coords.y & 8) == 0)
        {
            coords.x += ((coords.x / pxbase) + 1) * pxbase; // 1st, 3rd 'block' of 8 rows of pixels, offset by panel width in DMA buffer
        }
        else
        {
            coords.x += (coords.x / pxbase) * pxbase; // 2nd, 4th 'block' of 8 rows of pixels, offset by panel width in DMA buffer
        }

        coords.y = (coords.y >> 4) * 8 + (coords.y & 0b00000111);

  return coords;
}
NazarDoeH commented 2 months ago

It Works! https://github.com/user-attachments/assets/30547d3c-226c-4c1a-84c4-2b950d24d3cc

board707 commented 2 months ago

It should works with other library functions - lines, text ans so on

NazarDoeH commented 2 months ago

But not really... image

NazarDoeH commented 2 months ago

Nevermind

image

NazarDoeH commented 2 months ago

Almost right. But thanks! image

board707 commented 2 months ago

It looks like a problem with this test code and not with matrix pattern. All text and lines itself are displayed correct, the issue is with positioning only. If you show the code, I would see it tomorrow.

NazarDoeH commented 2 months ago

Yeh. Thanks for your help!

I will close this issue.

brianmackessy commented 1 month ago

@NazarDoeH Do you have a link to where you purchased your panel(s)? And what microcontroller are you using? I saw you got your setup working correctly!

NazarDoeH commented 1 month ago

@brianmackessy Hi (・ω・)ノ゙

I ordered here: https://www.aliexpress.com/item/1005003653914774.html

Board: ESP-Wroom-32