96x64px matrix (6x 32x32 1/8 scan panels) not displaying the bottom row
mozzhead164 opened this issue ยท 9 comments
Hello @mrfaptastic...first of all a thankyou for putting this library together over many MANY hours work! ๐
I am having issue with displaying on a set of 6No. 32x32 1/8 scan (so the label says) panels.
Outdoor P6 panel with code P6-3535(27)-8S-HL1.0
Driver Chip - ICN2037BP
Latch Chip - SM5166PC
Trying to use an Adafruit MatrixPortal S3 to drive these panels (So also using custom pin configuration)
Panels are wired according to the below diagram...
The library works absolutely fine with 1/2/3 panels all in the same row. Text and Shapes are displayed OK.
Problem arises when I chain another 3 panels underneath to produce a 2 row 96x64px panel.
Again the first three panels still behave, but nothing is displayed on the bottom row of panels.
I have tried many different combinations of the setup variables, and cannot get it to work properly.
I have 'glued' together two of your examples, "Four_Scan_Panel" and "ChainedPanels" - (Code Pasted Below)
Could it be something to do with 'FOUR_SCAN_32PX_HIGH' needing to be 'FOUR_SCAN_64PX_HIGH' instead?
I've tried that and it seems to product garbage results. Code Below.
I have also had to include....
mxconfig.driver = HUB75_I2S_CFG::ICN2038S;
...To get the panels to work with the IC that they use.
As a test, I have also tried removing the print text functions in loop() and just writing a fillScreen(RED), and interestingly all 6 of the panels light up red. But I cannot get the bottom half (row 2 - panels 4,5,6) of the display to display any text.
#include <Arduino.h>
#include "ESP32-HUB75-MatrixPanel-I2S-DMA.h"
#include "ESP32-VirtualMatrixPanel-I2S-DMA.h"
#define R1_PIN 42
#define G1_PIN 41
#define B1_PIN 40
#define R2_PIN 38
#define G2_PIN 39
#define B2_PIN 37
#define A_PIN 45
#define B_PIN 36
#define C_PIN 48
#define D_PIN 35
#define E_PIN 21
#define LAT_PIN 47
#define OE_PIN 14
#define CLK_PIN 2
// Panel configuration
#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 2 // Number of rows of chained INDIVIDUAL PANELS
#define NUM_COLS 3 // 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 true
#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
VirtualMatrixPanel *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::ICN2038S; // 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, VIRTUAL_MATRIX_CHAIN_TYPE);
// THE IMPORTANT BIT BELOW!
FourScanPanel->setPhysicalPanelScanRate(FOUR_SCAN_32PX_HIGH);
}
void loop() {
// Print on each chained panel 1/8 module!
// This only really works for a single horizontal chain
for (int i = 0; i < NUM_ROWS*NUM_COLS; i++)
{
FourScanPanel->setTextColor(FourScanPanel->color565(255, 255, 255));
FourScanPanel->setCursor(i*PANEL_RES_X + 7, FourScanPanel->height()/3);
// Red text inside red rect (2 pix in from edge)
FourScanPanel->print(String(i+1));
FourScanPanel->drawRect(1,1, FourScanPanel->width()-2, FourScanPanel->height()-2, FourScanPanel->color565(255,0,0));
// White line from top left to bottom right
FourScanPanel->drawLine(0,0, FourScanPanel->width()-1, FourScanPanel->height()-1, FourScanPanel->color565(255,255,255));
}
delay(2000);
dma_display->clearScreen();
}
The code above produces the below output
Then, when I change the config to have;
#define NUM_ROWS 1 // Number of rows of chained INDIVIDUAL PANELS
#define NUM_COLS 6 // Number of INDIVIDUAL PANELS per ROW
The output then looks like this
Why are you not flipping the bottom row 6,5,4) upside down so that row is (4,5 6) (with all panels flipped around)?
Then you can use a much shorter cable.
That's that serpentine is:
#define SERPENT true
Read the chained panels documentation pdf for the graphical examples.
@mrfaptastic I have done as you asked and flipped the bottom row of tiles so they are all now upside down.
I am still getting the same output as the first image of my matrix, nothing displayed at all on the bottom row.
But interestingly, you can see a patch of white pixels on the bottom left of Panel 1 - as if its printing all of the bottom panel contents onto these few pixels, would you say that is correct from what you can see?
The SERPENT and TOPDOWN variables are both set HIGH
#define SERPENT true
#define TOPDOWN true
Can you see anything else in my code above that would prevent the bottom row from displaying?
There must be some bug in the virtual matrix class pixel remapping logic with 1/4 scan panels.
Actually, these defines aren't used anymore:
#define SERPENT true
#define TOPDOWN true
What example did you copy from that still had these? I thought I removed all references to this.
Can you please read the chain panels pdf?
Those two defines were from the 'Four_Scan_Panel' example, which I copied the entire source into PlatformIO before adding in the relevant parts from the 'ChainedPanels' example.
I have read the PDF a few times and have therefore added the below statement, which can be seen in the code in my first message.
#define VIRTUAL_MATRIX_CHAIN_TYPE CHAIN_TOP_RIGHT_DOWN
Also from the PDF, these two below examples seem to contradict each other.
Where Example 1) shows the ESP connected at the top right, with Panel 1 also at the top right (Using Top-Right-Down)
Then the second image shows Top-Right-Down configuration, but the Top right panel is #9 in that example...is that right?
Anyway, is there any way I can isolate the problem that you are suggesting?
The board I am using is the Adafruit MatrixPortal S3 - which is a pain in the a*se to program, I am still unable to get any debug output from the serial monitor, it just stays blank. That's another issue - but its slowing my progress.
...is there an easy way to slow down pushing out panel updates so that the scan is viewable by eye?
Also waiting for the supplier to send me a datasheet for the panels. So should have more details in the coming days.
I'll take a look. It's most certainly some bug with the VirtualMatrix class. 1/4 Scan support has always been a bit of hack, but given when you only have one row of output, all six panel display something, the class VirtualMatrix must be re-mapping the pixels intended for the bottom row into non-existent co-ordinates, and thus, they remain black.
Yes, absolutely makes sense to me. Let me know if I can do anything to assist in any way!
Drop us your Paypal if you want and I will drop you some coin ๐
I have come back to this project after some months away, I still can't find a solution to this problem.
The library code seems to be printing to pixels that are out of the coordinate bounds of the screen.
I have written a simple test loop which just iterates drawPixel() over the x axis and then the y.
The panel lights up the top row of panels, but the second row stays dark.
I have printed the coordinates out to Serial monitor at different stages of the getCoords() function:
I have only printed rows 0 and 32 to be more concise.
0) req.xy ( 0, 0) . chain.xy ( 64, 0) ... Physical.xy: (160, 0)
0) req.xy ( 1, 0) . chain.xy ( 65, 0) ... Physical.xy: (161, 0)
0) req.xy ( 0, 0) . chain.xy ( 64, 0) ... Physical.xy: (160, 0)
0) req.xy ( 2, 0) . chain.xy ( 66, 0) ... Physical.xy: (162, 0)
0) req.xy ( 1, 0) . chain.xy ( 65, 0) ... Physical.xy: (161, 0)
0) req.xy ( 3, 0) . chain.xy ( 67, 0) ... Physical.xy: (163, 0)
0) req.xy ( 2, 0) . chain.xy ( 66, 0) ... Physical.xy: (162, 0)
0) req.xy ( 4, 0) . chain.xy ( 68, 0) ... Physical.xy: (164, 0)
0) req.xy ( 3, 0) . chain.xy ( 67, 0) ... Physical.xy: (163, 0)
0) req.xy ( 5, 0) . chain.xy ( 69, 0) ... Physical.xy: (165, 0)
0) req.xy ( 4, 0) . chain.xy ( 68, 0) ... Physical.xy: (164, 0)
0) req.xy ( 5, 0) . chain.xy ( 69, 0) ... Physical.xy: (165, 0)
0) req.xy (58, 0) . chain.xy (122, 0) ... Physical.xy: (250, 0)
0) req.xy (59, 0) . chain.xy (123, 0) ... Physical.xy: (251, 0)
0) req.xy (58, 0) . chain.xy (122, 0) ... Physical.xy: (250, 0)
0) req.xy (60, 0) . chain.xy (124, 0) ... Physical.xy: (252, 0)
0) req.xy (59, 0) . chain.xy (123, 0) ... Physical.xy: (251, 0)
0) req.xy (61, 0) . chain.xy (125, 0) ... Physical.xy: (253, 0)
0) req.xy (60, 0) . chain.xy (124, 0) ... Physical.xy: (252, 0)
0) req.xy (62, 0) . chain.xy (126, 0) ... Physical.xy: (254, 0)
0) req.xy (61, 0) . chain.xy (125, 0) ... Physical.xy: (253, 0)
0) req.xy (63, 0) . chain.xy (127, 0) ... Physical.xy: (255, 0)
0) req.xy (62, 0) . chain.xy (126, 0) ... Physical.xy: (254, 0)
0) req.xy (63, 0) . chain.xy (127, 0) ... Physical.xy: (255, 0)
1) req.xy ( 0, 32) . chain.xy ( 63, 31) ... Physical.xy: (127, 16)
1) req.xy ( 1, 32) . chain.xy ( 62, 31) ... Physical.xy: (126, 16)
1) req.xy ( 0, 32) . chain.xy ( 63, 31) ... Physical.xy: (127, 16)
1) req.xy ( 2, 32) . chain.xy ( 61, 31) ... Physical.xy: (125, 16)
1) req.xy ( 1, 32) . chain.xy ( 62, 31) ... Physical.xy: (126, 16)
1) req.xy ( 3, 32) . chain.xy ( 60, 31) ... Physical.xy: (124, 16)
1) req.xy ( 2, 32) . chain.xy ( 61, 31) ... Physical.xy: (125, 16)
1) req.xy ( 4, 32) . chain.xy ( 59, 31) ... Physical.xy: (123, 16)
1) req.xy ( 3, 32) . chain.xy ( 60, 31) ... Physical.xy: (124, 16)
1) req.xy ( 5, 32) . chain.xy ( 58, 31) ... Physical.xy: (122, 16)
1) req.xy ( 4, 32) . chain.xy ( 59, 31) ... Physical.xy: (123, 16)
1) req.xy ( 5, 32) . chain.xy ( 58, 31) ... Physical.xy: (122, 16)
1) req.xy (58, 32) . chain.xy ( 5, 31) ... Physical.xy: ( 37, 16)
1) req.xy (59, 32) . chain.xy ( 4, 31) ... Physical.xy: ( 36, 16)
1) req.xy (58, 32) . chain.xy ( 5, 31) ... Physical.xy: ( 37, 16)
1) req.xy (60, 32) . chain.xy ( 3, 31) ... Physical.xy: ( 35, 16)
1) req.xy (59, 32) . chain.xy ( 4, 31) ... Physical.xy: ( 36, 16)
1) req.xy (61, 32) . chain.xy ( 2, 31) ... Physical.xy: ( 34, 16)
1) req.xy (60, 32) . chain.xy ( 3, 31) ... Physical.xy: ( 35, 16)
1) req.xy (62, 32) . chain.xy ( 1, 31) ... Physical.xy: ( 33, 16)
1) req.xy (61, 32) . chain.xy ( 2, 31) ... Physical.xy: ( 34, 16)
1) req.xy (63, 32) . chain.xy ( 0, 31) ... Physical.xy: ( 32, 16)
1) req.xy (62, 32) . chain.xy ( 1, 31) ... Physical.xy: ( 33, 16)
1) req.xy (63, 32) . chain.xy ( 0, 31) ... Physical.xy: ( 32, 16)
The req.xy is the x,y coords passed to drawPixel()
The chain.xy is virt_x and virt_y
The Physical.xy is coords.x and coords.y
Can you spot any weird behaviour in this output?
..and would that lead to any other test code that I could upload to the board to test why this is happening?
It seems that once the 2nd row of panels is reached, the Y coordinates are wrapping back around to 31->0 instead of going between 32->63
The library code seems to be printing to pixels that are out of the coordinate bounds of the screen.
Yes, it seems the bug in VirtualMatrixPanel::getCoords()
function line 405.
In the code for FOUR_SCAN_32PX_HIGH
panels the line:
coords.y = (virt_y >> 4) * 8 + (virt_y & 0b00000111);
accidentally used virt_y
instead of coords.y
.
As a result, if your configuration uses a multiple rows of panels, the coords.y
becomes greater than the real height of the panel.
The solution is to change the line of 405 as:
coords.y = (coords.y >> 4) * 8 + (coords.y & 0b00000111);
@mozzhead164
Could you please check this assumption?