hzeller / rpi-rgb-led-matrix

Controlling up to three chains of 64x64, 32x32, 16x32 or similar RGB LED displays using Raspberry Pi GPIO
GNU General Public License v2.0
3.59k stars 1.15k forks source link

Problem with panels 32x32 with scan rate 1:8 #66

Closed currentlysober closed 6 years ago

currentlysober commented 8 years ago

Dear Henner,

a few days ago I found matrixes 32x32 with 1:8 scan rate. I received one piece to try to use it but I have a big problem to print out complete information. Completely strange things show up - text is visible in higher part of the panel and first characters are below, following characters over the first ones. I use 1:8 to use normal 16x32 panels but I do not know how to change paramteres or modify the library a little to use those panels. I would like to program a little to have them in the way that later we connect 3 chains in parallel and they still work fine. So I guess -r and -P cannot help in this moment (I tried :) ) I was trying to understand idea of variables

const int rows; // Number of rows. 16 or 32. const int parallel; // Parallel rows of chains. 1 or 2. const int height; // rows * parallel const int columns; // Number of columns. Number of chained boards * 32.

but I'm afraid it's a dead end and I do not want to break the panel with blind shots. Yes, I saw another issue regarding various scan rate but it was mostly about 1:4. The panels I found have only info regarding 1:8 scan rate - and I guess the rest is as in 'normal' 32x32 panels. Could you please help me and give me some tips, information, how to program 32x32 panels with 1:8 scan rate? I will be really grateful. Best regards Daniel.


Dear Henner, here is what shows up after setting -r32 -P1 -c1 and printing "ABCDEFGHIJ" - photo attached. It seems that not only it has scan rate 1:8 in rows but also some 1:16 in columns. Am I right? Could you please tell me which part of library is responsible for maintaining this? I will be really grateful. It seems that new type of panels start to be available. Best regards!

win_20150912_202735

hzeller commented 8 years ago

I have not seen these displays, so I can't give definitive answer. However, Kent, one of the users of this library, faced a similar problem and he did a remapping using the transformer technique. A transformer is a way to re-map pixels in a way that they are useful. See

https://github.com/hzeller/rpi-rgb-led-matrix/blob/master/include/canvas.h#L51

Also some implementations are here: https://github.com/hzeller/rpi-rgb-led-matrix/blob/master/lib/transformer.cc

The following is what kent wrote. Let me know if this works for you, I might just add this transformer to the general distribution as this seems to be a newer trend in these displays.

--- Kent wrote ------

I managed to work out the pixel mapping and created a transformer to remap the pixels. It was remarkably simple (once I figured out what I was doing). I basically copied and modified your LargeSquare64x64Transformer:

int Snake8x2Transformer::TransformCanvas::width() const {
  return delegatee_->width() / 2;
}

int Snake8x2Transformer::TransformCanvas::height() const {
  return delegatee_->height() * 2;
}

void Snake8x2Transformer::TransformCanvas::SetPixel(int x, int y, uint8_t red, uint8_t green, uint8_t blue) {
  int new_x;
  int new_y;

  new_x = ((x / 8) * 16) + (x % 8);
  if ((y & 4) == 0) {
    new_x += 8;
  }

  new_y = ((y / 8) * 4) + (y % 4);

  delegatee_->SetPixel(new_x, new_y, red, green, blue);
}

I also had to set rows=8, chains=6, parallel=3 as the panels appear to be using 1:4 multiplexing (hence the width/2 and height*2 in the transform).
The very limited info on these panels refers to the multiplexing as "snake" and is supposed to minimise flicker. For a single panel, the 16 8x4 pixel blocks are arranged thus:

 2 | 4 | 6 | 8    y = 0..3   (lines 1..4 uses second set of rgb data pins)
 1 | 3 | 5 | 7    y = 0..3   (lines 5..8 uses first set of rgb data pins)
10 | 12| 14| 16   y = 4..7   (lines 9..12 uses second set of rgb data pins)
 9 | 11| 13| 15   y = 4..7   (lines 13..16 uses first set of rgb data pins)
             +--- x = 48..55 (odd blocks) or x = 56..63 (even blocks)
         +------- x = 32..39 (odd blocks) or x = 40..47 (even blocks)
     +----------- x = 16..23 (odd blocks) or x = 24..31 (even blocks)
 +--------------- x = 0..7 (odd blocks) or x = 8..15 (even blocks) 

so the mapping for the corners is as follows: 0,0 -> 8,0 31,0 -> 63,0 0,15 -> 0,7 31,15 -> 31,7

I hope someone finds this useful.

hzeller commented 8 years ago

Can you tell me where you got this panel ? I might want to try getting one as well for experiments and maintenance of the library.

hzeller commented 8 years ago

If you have 1:8, then you probably need to start out with a setting of -r 16 (because it has 8 rows doubled up) and -c 2 (as it internally requires 64 pixels to push through to have 64x16 = 32x32 pixels.

In order to figure out the snake mapping for this, you should light one row after the other to see how things are 'folded' on the screen. So on your 64x16 screen, fill the first 64 pixels (maybe the first half with red, the second half with blue or so so that you can better trace what is happening). You will see how the line is folded on the screen. Then do that for each line and get an idea. After that, you can easily write a transformer.

Looking at your picture, it looks like the lower middle quarter is the first 16 pixels, folled by the top quarter.

How do you know that your display is a 1:8 ? If there is some documentation for it, then it should probably say as well something about the pixel mapping. Does the display only have two connectors on the back (one in, one out) ? Are the connectors labelled ? If it is 1:8, then the A, B, C, D lines should have the 'D' missing.

hzeller commented 8 years ago

Did you get your display remapped correctly ?

ts4pi commented 8 years ago

Hi, unfortunately I bought the same display. I only read 32 x 32 and ignored the 1:8 scan. I made the same experience. Electrical this modules are 16 x 64. There are twice the amount of shift register on the module. The Information is shifted through the the upper half and then trough the lower half. So it works like two 16 x 32 Matrixes which are chained but arranged below each other.

special modules

ts4pi commented 8 years ago

Sorry I sent this to fast: With the rearranged Pixels You have to use -r16 -c 6 instead of -r32 -c3

hzeller commented 8 years ago

Can you write a transformer that can properly re-map these pixels to be contributed to the project with a pull request ?

hzeller commented 8 years ago

Any progress on this ? Did you write a transformer that works with your display ? Other people that have such a display could possibly benefit.

ts4pi commented 8 years ago

Am 12.11.2015 um 18:05 schrieb Henner Zeller:

Any progress on this ? Did you write a transformer that works with your display ? Other people that have such a display could possibly benefit.

— Reply to this email directly or view it on GitHub https://github.com/hzeller/rpi-rgb-led-matrix/issues/66#issuecomment-156167704.

Sorry for late response, but there was so much trouble at work. Till now I don't have a transformer. There are 2 main reasons: 1) I didn't have programmed anything for the last decade and I have allmost none experience in programming c++. Even reading and understanding is sometimes difficult. 2) I think a transformer won't work with every kind of picture. The ppm to show has to be expanded to have a size modulo 32 in both directions.

So when i find time in next week(s) I'll write a offline transformer ( in C not C++) because that will be much easier (for me) The transformed ppm can be converted back to png and so I can see easily if the transformer has done its job.

I'll keep You informed. Best regards Thomas

hzeller commented 8 years ago

The transformer is only there to do the basic pixel mapping that determines where a SetPixel(x, y) shows up on the screen. This essentially provides you a new canvas where pixels show up where you expect them :)

Once you have that, you can display any image you want, including other things you want to do with the image to be displayed. So your point (2) is just what you want to do in your application.

In order to get started and understand how the mapping is now, you can write a simple application that moves a pixel, one by one, to each location

  for (int y = 0; y < matrix->height(); ++y) {
     for (int x = 0; x < matrix->width(); ++x) {
        matrix->SetPixel(x, y, 255, 255, 255);
     }
  }

Then you can see how pixels 'jump around' and write a tranformer that counters that.

currentlysober commented 8 years ago

Dear Henner and Thomas, I will send the solution I worked out to Henner - and Henner, maybe in the next update you could include it...? So people won´t have trouble with this kind of matrix. Sadly, so far it works with simple text. I didn´t have time to fight to display images (jpg, gif) correctly (and some time ago I noticed that remapping doesn´t work with images). Regards! Daniel

hzeller commented 8 years ago

Don't worry about the images, I think I never properly added the remapping code to the image app. Will do that soon.

hzeller commented 8 years ago

FYI, I've added the necessary scaffolding to the image viewer last week that it can easily accept a Transformer. So once you have the transformer, the image viewer will work with it as well.

currentlysober commented 8 years ago

Dear all, thank you, I will check image viewer today. I sent the code to you Henner, so that maybe it would appear in next updates. Anyway, here is the way of transforming:

int LargeSquare64x64Transformer::TransformCanvas::width() const {
  return delegatee_->width() / 2;  }
int LargeSquare64x64Transformer::TransformCanvas::height() const {
  return delegatee_->height() * 2; }
void LargeSquare64x64Transformer::TransformCanvas::SetPixel(int x, int y, uint8_t red, uint8_t green, uint8_t blue) {
  int new_x, new_y;
  new_x = ((x / 16) * 32) + (x % 16);
  if ((y & 8) == 0) {
      new_x += 16; }
  new_y = ((y / 16) * 8) + (y % 8);
  delegatee_->SetPixel(new_x, new_y, red, green, blue);  }

Regards

KentWalker commented 8 years ago

HI all,

Another issue with the 32x32 displays is they may be 4 sub panels (instead of two). You might need to change the define in framebuffer.cc to SUBPANELS 4.

rows will be 32, chain will be twice the number of panels linked.

Hope this is helpful

ts4pi commented 8 years ago

Hi, back again after a while. Last few weeks we spent to build a frame for the moduls. With the help from currentlysober I could modify the shown transformer a little bit and now it works great.

int myTransformer::TransformCanvas::width() const { return delegatee->width() / 2; } int myTransformer::TransformCanvas::height() const { return delegatee->height() * 2; }

void myTransformer::TransformCanvas::SetPixel(int x, int y, uint8_t red, uint8_t green, uint8_t blue) { int new_x, new_y; new_x = ((x / 32) * 64) + (x % 32); if ((y & 8) == 0) { new_x += 32; } newy = ((y / 16) * 8) + (y % 8);
delegatee
->SetPixel(new_x, new_y, red, green, blue); } For 3 chains of 8 modules I have to call sudo ./ledmatrix -r16 -c16 -P3 -D1 xyz.ppm

Thanks a lot, I'm so happy

currentlysober commented 8 years ago

Dear All, I managed to contact the seller of my LED modules and I was told that the modules have 1/4 scanning. It is funny because I managed to run those modules with 1/8 scanning. However, with 1/8 they are significantly less bright than when I run with 1/4 scanning. This is why in some other thread I asked about led's brightness. And running with correct 1/4 scanning is highly important to me. Maybe some other users will use this modules too. I am writing here because Kent managed to program 1/4 scan modules. Sadly, my LED modules work in a little bit different way. And I cannot make them working. I will update you with my progress but so far I have no results.

When I run it without transformer (with text "ABCDEFGHIJKLMNO" from 0,0 point), I have this: 20160623_215231786_ios

As you can see, the module contains 16 areas, each 16x4 leds: XXXXXX | XXXXXX XXXXXX | XXXXXX YYYYYY| XXXXXX XXXXXX | XXXXXX XXXXXX | XXXXXX XXXXXX | XXXXXX ZZZZZZ | XXXXXX XXXXXX | XXXXXX

What is interesting, upper part of first characters (ABCD) is visible in area YYYYY and bottom part in ZZZZZ area. Moreover, some parts do not show data even if I write in various positions....

Could you please share any idea with me to help me out with this issue? Thank you in advance.

KentWalker commented 8 years ago

Hi currentlysober,

Try this transform which has worked for my batch of 32x32 panels:

new_x = ((x / 16) * 32) + (x % 16); if ((y & 8) == 0) { new_x += 16; } new_y = ((y / 16) * 16) + (y % 8);

Also in your transform class have:

int myTransformer::TransformCanvas::width() const { return delegatee->width() / 2; } int myTransformer::TransformCanvas::height() const { return delegatee->height() ; }

Change the define in framebuffer.cc to SUBPANELS 4 and remake the librgbmatrix library.

Try row = 32 and chains = double the number of panels in a chain.

Let me know how that works. Cheers

currentlysober commented 8 years ago

Hi Kent,

thank you for the answer! Below the results. According to the supplier, panels P5 and P6 which are outdoor panels should have 1/4 scanning because of brightness requirements. It would be really good to make them working and later put the code in Henner's library.

  1. I modified the code exactly as you wrote me. The result is the same as it was before - panels show dim information. It shows pixels correctly (photo-right side), but with (I bet) 60-70% of possible brightness. I set row=32 which I believe gives 1:16 scanning, but the supplier had written me it has 1/4 scanning. It is correct because we are close to the correct values (more below).
  2. Another experiment: I set nearly everything as you told me except #define SUBPANELS 2 (I leave a value '2'). I changed also row=8. The result is not perfect but we are close (photo-left side)!
  3. Kent, I think if you have 1:4 scanning, you can also check the difference. Maybe with small tips from Henner we can modify Y values so the text looks fine?
  4. Last thing: I modified LargeSquare64x64Transformer instead of creating new one. I believe it is fine. I activate it by line: canvas->SetTransformer(new rgb_matrix::LargeSquare64x64Transformer()); but what I noticed (using printf) that the program doesn't enter those 2 places (maybe this is an issue) :

int LargeSquare64x64Transformer::TransformCanvas::width() const { return delegatee->width() / 2; } int LargeSquare64x64Transformer::TransformCanvas::height() const { return delegatee->height() ; }

Results below. If we join parts of characters with keeping row=8 (higher brightness) scanning, it will be perfect: led difference

Regards!

currentlysober commented 8 years ago

An update: I think there is some missing part in a source code in case of row=8 because there is no way to light-up pixels in blind spots (left photo). I light up all pixels from point 0,0 to 96,96 (3x3 panels) and still there are blind spots (theoretically there shouldn't be any). Am I right?

20160

KentWalker commented 8 years ago

What do you get when rows=4 and sub_panel=1? Or even rows=2 and sub_panels=1?

currentlysober commented 8 years ago

Hi, interesting thing happens: both with row=4 sub_panel=1 and row=2 sub_panel=1 the brightness is about 70% of maximum. still, the best result gives row=8, sub_panel=2 (100% brightness) but I cannot find a way to light up the rest of leds.

result

quite weird.

wiltwong commented 8 years ago

I had a similar issue with this panel which was laid out as a chain of two 8x64 panels, the layout was the following:

Panel 1, Y=0, X=32->X=63 Panel 1, Y=1, X=32->X=63 Panel 1, Y=2, X=32->X=63 Panel 1, Y=3, X=32->X=63 Panel 1, Y=4, X=32->X=63 Panel 1, Y=5, X=32->X=63 Panel 1, Y=6, X=32->X=63 Panel 1, Y=7, X=32->X=63 Panel 1, Y=0, X=0->X=31 Panel 1, Y=1, X=0->X=31 Panel 1, Y=2, X=0->X=31 Panel 1, Y=3, X=0->X=31 Panel 1, Y=4, X=0->X=31 Panel 1, Y=5, X=0->X=31 Panel 1, Y=6, X=0->X=31 Panel 1, Y=7, X=0->X=31 Panel 2, Y=0, X=32->X=63 Panel 2, Y=1, X=32->X=63 Panel 2, Y=2, X=32->X=63 Panel 2, Y=3, X=32->X=63 Panel 2, Y=4, X=32->X=63 Panel 2, Y=5, X=32->X=63 Panel 2, Y=6, X=32->X=63 Panel 2, Y=7, X=32->X=63 Panel 2, Y=0, X=0->X=31 Panel 2, Y=1, X=0->X=31 Panel 2, Y=2, X=0->X=31 Panel 2, Y=3, X=0->X=31 Panel 2, Y=4, X=0->X=31 Panel 2, Y=5, X=0->X=31 Panel 2, Y=6, X=0->X=31 Panel 2, Y=7, X=0->X=31

. Wilton

currentlysober commented 8 years ago

I'm afraid this this different module with different scanning. And different pixels map.

To sum up, there are blank spots and there is no possibility to turn those pixels on. I marked those blank spots in red frames. Maybe someone managed to deal with 1:4 scan modules?

1140a140-3c80-11e6-9df6-40eda07a8406

justinpham0210 commented 7 years ago

Hi Experts, Any updates on this case? I have same issue with this scan rate :(. To be honest i'm not a developer at all so looking forward to hear some good improvement :)

Thanks justin

gadag99 commented 7 years ago

Hi @hzeller @ts4pi I written class as myTransformer, I am calling these calls in main like myTransformer *transformer = new myTransformer(); matrix->SetTransformer(transformer); before Canvas *canvas = matrix;. I want to know that is this the correct way? because i tried with this but i am not getting proper output .My panel have 1:8 scan rate 32x32. How i can modify in demo-main and text.cc?

Regards, Praveen

playaspec commented 6 years ago

@currentlysober I'm pretty sure you're wired for HUB75, not HUB75E. That's why you're getting blank areas. WIth HUB75 there's four address lines: A,B,C,D. Four bits gets you 16 lines, which is what your pictures show. HUB75E has FIVE address lines, A-E. Address line E is on pin 8, which is tied to GND on HUB75. Fix your wiring, because no amount of code fiddling is going to get you there!

HummingBuddha commented 6 years ago

Hello Everyone I am using P5 32x32 8S HUB75 with A B C lines with HZeller libraries. I have used ts4pi transformer and also tried with currentlysober Jun 24, 2016 transformer changes but nothing worked for me. I have tried to change number of rows and chains but in vain. Have tried both on a single board as well on a 9 chained 2 parallel boards and obviously have the same issue. I have attached images for your ref.. Please let me know if you need any inputs to help me to solve my issue.

P.S- HZeller and team seriously great work and helping lots of ppl around the globe. Thank you. img_20180110_181505 ![Uploading IMG_20180110_181501.jpg…]() ![Uploading IMG_20180110_181457.jpg…]() ![Uploading IMG_20180110_181450.jpg…]()

hzeller commented 6 years ago

Please check out the new option --led-multiplexing https://github.com/hzeller/rpi-rgb-led-matrix#multiplexing It does the mapping built into the library (and can also be used from Python.) (You need to do a fresh checkout and compile, this just went in).

yoeckoe commented 5 years ago

The transformer is only there to do the basic pixel mapping that determines where a SetPixel(x, y) shows up on the screen. This essentially provides you a new canvas where pixels show up where you expect them :)

Once you have that, you can display any image you want, including other things you want to do with the image to be displayed. So your point (2) is just what you want to do in your application.

In order to get started and understand how the mapping is now, you can write a simple application that moves a pixel, one by one, to each location

  for (int y = 0; y < matrix->height(); ++y) {
     for (int x = 0; x < matrix->width(); ++x) {
        matrix->SetPixel(x, y, 255, 255, 255);
     }
  }

Then you can see how pixels 'jump around' and write a tranformer that counters that.

@hzeller, i have some problem with my 64*32 rgb panel - 4 mm pitch, --> i think like this, but its totally different https://www.adafruit.com/product/3826

i dont know scan rate for my panel, i try your code (but in arduino, and i use Mega).
the result is two pixel move together (not a pixel) , dont know why.

if i use adafruit library, the result is like this

capture

you can see on "G" char, there is one gap. can you explain what should i do? thanks for your help.