Skip to content

P5 Outdoor Chain Panel #765

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

Open
voleminhtripro opened this issue Mar 6, 2025 · 7 comments
Open

P5 Outdoor Chain Panel #765

voleminhtripro opened this issue Mar 6, 2025 · 7 comments

Comments

@voleminhtripro
Copy link

voleminhtripro commented Mar 6, 2025

Has anyone been able to control two P5 Outdoor LED panels arranged vertically?
It only works on LED panel 1, but LED panel 2 doesn't display any data. I'm sure the signal cables are connected correctly.

@voleminhtripro
Copy link
Author

#include <Arduino.h>
#include <ESP32-HUB75-VirtualMatrixPanel_T.hpp>

#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 VDISP_NUM_ROWS 2 // Number of rows of individual LED panels
#define VDISP_NUM_COLS 1 // Number of individual LED panels per row

#define PANEL_CHAIN_LEN 2 // Don't change

#define PANEL_CHAIN_TYPE CHAIN_TOP_RIGHT_DOWN

#define PANEL_SCAN_TYPE FOUR_SCAN_32PX_HIGH

MatrixPanel_I2S_DMA* dma_display = nullptr;

using MyScanTypeMapping = ScanTypeMapping<PANEL_SCAN_TYPE>;

VirtualMatrixPanel_T<PANEL_CHAIN_TYPE, MyScanTypeMapping>* virtualDisp = nullptr;

void setup() {
Serial.begin(115200);

HUB75_I2S_CFG mxconfig(
PANEL_RES_X * 2, // DO NOT CHANGE THIS
PANEL_RES_Y / 2, // DO NOT CHANGE THIS
PANEL_CHAIN_LEN);

mxconfig.i2sspeed = HUB75_I2S_CFG::HZ_20M;
mxconfig.clkphase = false;
//mxconfig.driver = HUB75_I2S_CFG::FM6126A;

dma_display = new MatrixPanel_I2S_DMA(mxconfig);
dma_display->begin();
dma_display->setBrightness8(128); //0-255
dma_display->clearScreen();

virtualDisp = new VirtualMatrixPanel_T<PANEL_CHAIN_TYPE, MyScanTypeMapping>(

VDISP_NUM_ROWS,
VDISP_NUM_COLS,
PANEL_RES_X,
PANEL_RES_Y);

virtualDisp->setDisplay(*dma_display);

for (int y = 0; y < virtualDisp->height(); y++) {
for (int x = 0; x < virtualDisp->width(); x++) {

  uint16_t color = virtualDisp->color565(96, 0, 0);  // red

  if (x == 0) color = virtualDisp->color565(0, 255, 0);                           // g
  if (x == (virtualDisp->width() - 1)) color = virtualDisp->color565(0, 0, 255);  // b

  virtualDisp->drawPixel(x, y, color);
  delay(1);
}

}

delay(100);
virtualDisp->clearScreen();
virtualDisp->drawDisplayTest(); // re draw text numbering on each screen to check connectivity
Serial.println(virtualDisp->height());
Serial.println(virtualDisp->width());
virtualDisp->setCursor(5, 6);
virtualDisp->setTextColor(dma_display->color565(255, 0, 0));
virtualDisp->println("Con Cac");
}

void loop() {

// Do nothing here.
delay(100);
}

@justintemplar
Copy link

I am also having this issue, similar code setup and have been trying so many combinations.
I can get them to work horizontally, like COL = 2 and ROW = 1. But not ROW = 2 and COL = 1, vertically stacked.

@mrcodetastic
Copy link
Owner

Can you test first without using the Virtual Matrix class? Do you get output on the second chained panel when using using dma_display and setting the chain length to 2?

@sparcman1
Copy link

sparcman1 commented May 11, 2025

The cause is that when the row is 2 or more, the value of line == y becomes 16 or more in 1/8 scan.

I tested and succeeded with ZigZag.
#define VIRTUAL_MATRIX_CHAIN_TYPE CHAIN_TOP_RIGHT_DOWN_ZZ

I am currently using it successfully with 2x3.

Please refer to the part below that was added directly without creating a separate class. (sparcman add)

inline VirtualCoords VirtualMatrixPanel::getCoords(int16_t virt_x, int16_t virt_y)
{
.
.
.
.

if ((panel_scan_rate == FOUR_SCAN_32PX_HIGH) || (panel_scan_rate == FOUR_SCAN_64PX_HIGH)) {
if (panel_scan_rate == FOUR_SCAN_64PX_HIGH)
{
// #345 (comment)
if ((virt_y & 8) != ((virt_y & 16) >> 1)) { virt_y = (virt_y & 0b11000) ^ 0b11000 + (virt_y & 0b11100111); }
}

    /* Convert Real World 'VirtualMatrixPanel' co-ordinates (i.e. Real World pixel you're looking at
       on the panel or chain of panels, per the chaining configuration) to a 1/8 panels
       double 'stretched' and 'squished' coordinates which is what needs to be sent from the
       DMA buffer.

       Note: Look at the FourScanPanel example code and you'll see that the DMA buffer is setup
       as if the panel is 2 * W and 0.5 * H !
    */

    if ((virt_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
    }

    // http://cpp.sh/4ak5u
    // Real number of DMA y rows is half reality
    // coords.y = (y / 16)*8 + (y & 0b00000111);
    //coords.y = (virt_y >> 4) * 8 + (virt_y & 0b00000111);
    //coords.y = ((virt_y >> 4) << 3) + (virt_y & 0b00000111);  // Optimize the above

    // sparcman add
    //if (coords.y > 15) coords.y -= 16;  // <-- For checking LED during coordinate test
    int local_y = virt_y % panelResY;
    coords.y = (local_y & 0x07) + ((local_y >> 4) << 3);

}

.
.
.

Image

@board707
Copy link
Contributor

board707 commented May 11, 2025

Please refer to the part below that was added directly without creating a separate class. (sparcman add)

it seems for me that the lines below " // sparcman add" are the same as in the standard virtual panel class example.

@sparcman1
Copy link

I tried various methods using the standard library and examples, but it was not displayed from Row 2. I confirmed through debugging messages that it was not displayed when the physical y coordinate was 16 or more. In addition, when using CHAIN_TOP_RIGHT_DOWN, there was a problem with the coordinates not matching, and the calculation for this was complicated, so I gave up for the time being, and I confirmed that it works normally when using CHAIN_TOP_RIGHT_DOWN_ZZ.

@board707
Copy link
Contributor

test your setup with code below:

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
          }
      else
        {
           coords.x += (coords.x / panelResX) * panelResX; // 2nd, 4th 'block' of 8 rows of pixels
         }
      coords.y = (coords.y >> 4) * 8 + (coords.y & 0b00000111);
     return coords;
}

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

5 participants