Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

P10 32x16 1/4 SM16208SJ, DP74HC138B, MW245B, MW4953F - need help with tuning #677

Open
YuriiKrop opened this issue Sep 22, 2024 · 18 comments

Comments

@YuriiKrop
Copy link

Hi there!
I have 2 such panel and it fill as shown in the video:

video_2024-09-23_01-15-51.mp4

Help me with mapping, please

This is code fragment of getCoords() function I use:

  if ((coords.y & 4) == 0)
  {
    coords.x = (coords.x / pxbase) * 2 * pxbase  + pxbase  + 7 - (coords.x & 0x7);
  }
  else
  {
    coords.x += (coords.x / pxbase) * pxbase; 
  }
  coords.y = (coords.y >> 3) * 4 + (coords.y & 0b00000011);

  return coords;
@davemaster
Copy link

Greetings,

First, try to slowdown a little, but this was made already in hzeller rpi-rgb-led-matrix github, you only have to adapt it to this...

Second, provide your full code... better way, all files. Thanks

@board707
Copy link
Contributor

Hi @YuriiKrop
As I see, you got the coords conversion code from the discussion #622, isn't it? But the pattern of your panel is different from one, used in the discussion and the code is not suited.

I could help you to adjust the code. Firstly, we need step back and to see the pattern without any conversion , as was done in Part 2 of the #622 tutorial.
Please, show your full sketch, used to generate the video.

@YuriiKrop
Copy link
Author

Thanks for the quick reply!
Here is the full code for the previous video.
Yes, it from #622 discussion (your last message), with uint8_t pxbase = 8; and it do 100% fill my matrix.
Code without pxbase don't fill matrix on 100%, so I decide take this code.

/*************************************************************************
   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 32x16 1/4 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;
  }

  uint8_t pxbase = 8;  // pixel base
  if ((coords.y & 4) == 0)
  {
    coords.x = (coords.x / pxbase) * 2 * pxbase  + pxbase  + 7 - (coords.x & 0x7); // 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 >> 3) * 4 + (coords.y & 0b00000011);

  return coords;
}
/* ================================================== */
// Panel configuration
#define PANEL_RES_X 32 // Number of pixels wide of each INDIVIDUAL panel module. 
#define PANEL_RES_Y 16 // 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

@YuriiKrop
Copy link
Author

Here is pinout my ESP32:

#define R1_PIN_DEFAULT  4
#define G1_PIN_DEFAULT  12
#define B1_PIN_DEFAULT  13
#define R2_PIN_DEFAULT  14
#define G2_PIN_DEFAULT  15
#define B2_PIN_DEFAULT  21

#define A_PIN_DEFAULT   16
#define B_PIN_DEFAULT   17
#define C_PIN_DEFAULT   -1
#define D_PIN_DEFAULT   -1
#define E_PIN_DEFAULT   -1 // IMPORTANT: Change to a valid pin if using a 64x64px panel.
            
#define LAT_PIN_DEFAULT 32
#define OE_PIN_DEFAULT  33
#define CLK_PIN_DEFAULT 27

And I should say I use quite long flat cable, about 1 meter.
If necessary, I will make it shorter.

@YuriiKrop
Copy link
Author

And if I use variant without pxbase

if (((coords.y / 5)%2) == 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 / 10) * 5 + (coords.y % 5);
  return coords;

I get such picture

video_2024-09-23_11-23-36.mp4

@board707
Copy link
Contributor

Hi
First - please use a single panel for testing and change the settings accordingly:

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

Next, change the conversion as shown below:

if ((virt_y & 4) == 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 = (virt_y >> 3) * 4 + (virt_y & 0b00000011);

Run it and show the video.

@YuriiKrop
Copy link
Author

If I change it in code, I get Compilation error: 'virt_y' was not declared in this scope

So, I uncommented
FourScanPanel->setPhysicalPanelScanRate(FOUR_SCAN_16PX_HIGH);

set

#define NUM_ROWS 1 
#define NUM_COLS 1 

and replace fragment in ESP32-VirtualMatrixPanel-I2S-DMA.h

    {
       /* if ((coords.y & 4) == 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 >> 3) * 4 + (coords.y & 0b00000011);*/
    //***********************
	if ((virt_y & 4) == 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 = (virt_y >> 3) * 4 + (virt_y & 0b00000011);
	
	
	//*************************
	}

    return coords;
video_2024-09-23_11-53-13.mp4

@board707
Copy link
Contributor

I get Compilation error: 'virt_y' was not declared in this scope

Sorry, return to your code and try this

if ((coords.y & 4) == 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 >> 3) * 4 + (coords.y & 0b00000011);

As I see, you steel to use a two panels. Please use the only one.

@YuriiKrop
Copy link
Author

YuriiKrop commented Sep 23, 2024

I replaced the video because I forgot to comment FourScanPanel->setPhysicalPanelScanRate(FOUR_SCAN_16PX_HIGH);

video_2024-09-23_12-48-04.mp4

Ok, I have disabled the second panel physically

@board707
Copy link
Contributor

Hmmm...
Your video doesn't look quite right - it looks like two lines are being filled at the same time. It shouldn't be like that. Something wrong with A B C D E lines...

As for the pattern, this panel has a 16 pixel base.

Try this code

uint8_t pxbase =16;   // pixel base
if ((coords.y & 4) == 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 >> 3) * 4 + (coords.y & 0b00000011);

By the way, increase the delay in the loop() between outputting individual pixels to make it easier to see how the lines are being filled.

@YuriiKrop
Copy link
Author

video_2024-09-23_13-22-34.mp4

@YuriiKrop
Copy link
Author

A, B, C address lines are connected
But I think line C doesn't matter in 1/4
In any case, disconnecting it has no effect

@board707
Copy link
Contributor

Thanks to the longer delay, I now see the lines not being filled at the same time, but one pixel from the top, one from the bottom - and so on.
Interesting structure, I have not seen such. For testing further, try the last code, but set pixel base 1

@YuriiKrop
Copy link
Author

Wow!

video_2024-09-23_13-41-30.mp4

@YuriiKrop
Copy link
Author

YuriiKrop commented Sep 23, 2024

I connected the second panel and it works great.

I still don't believe it.
I think I tried all the libraries, and several different arduino modules.
Also before this I had other type panels, but they didn't show any signs of life at all, so I changed them to these.
Thank you very much!
You are a wizard, @board707

@board707
Copy link
Contributor

You are welcome :)

If using ESP32 is not a requirement, you can look at my DMD_STM32 library for RGB panels. It works on STM32 and rp2040 controllers. The advantage is that its code supports panels of practically any size, row driver type and pixel pattern, excluding only S-PWM type drivers.

@YuriiKrop
Copy link
Author

Actually I saw your library a couple of weeks ago and appreciated it as powerfull.
Especially noted the presence of the cyrillic fonts, may be it will be usefull for me.
And then I saw STM32 instead ESP32 and a little upset.
My project is amateur and based on ESP32, but now there is a reason to look at more advanced STM32 in a future.
In the meantime, I'll be studying this library.
Thanks again!

@board707
Copy link
Contributor

@YuriiKrop
Keep in mind that the library also supports Raspberry Pico RP2040 boards. Perhaps this will be more convenient for you than stm32

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants