Open YuriiKrop opened 2 months ago
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
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.
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
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.
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
https://github.com/user-attachments/assets/91bf9e65-9f89-45f5-8057-b69357d6a960
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.
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;
https://github.com/user-attachments/assets/8e7a01a0-c271-40c2-9627-04df5eba6800
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.
I replaced the video because I forgot to comment FourScanPanel->setPhysicalPanelScanRate(FOUR_SCAN_16PX_HIGH);
https://github.com/user-attachments/assets/a9261d8c-6120-4886-a75a-56b6de8d9614
Ok, I have disabled the second panel physically
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.
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
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
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
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.
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!
@YuriiKrop Keep in mind that the library also supports Raspberry Pico RP2040 boards. Perhaps this will be more convenient for you than stm32
Hi there! I have 2 such panel and it fill as shown in the video:
https://github.com/user-attachments/assets/04af0f69-7d3c-47d3-aea5-318c1011493c
Help me with mapping, please
This is code fragment of getCoords() function I use: