I need guidance in mapping 5 separate 8x8 WS2812b matrices so software sees them as one.
Top left corner is pixel #1, bottom pixel is #64. Next board - top left is #65 and lower right is #128.
How do I map software so that location from pixel #1 runs straight through (across) so when it gets to #8 the next step will be #65 through #72 then next matrix panel. How is this actually accomplished? Any and all pointers would be greatly appreciated.
One way is to daisy chain them so they are now one longer strip of 5 * 64 (320) pixels, connected to one pin and declared in the code as one object.
Writing is fairly fast, if you have the time this is the easiest way to go by far.
Another way, what you have actually asked for, is to write functions that accept pixel numbers from 0 to 319, and within those functions figure out which strip to direct the data to.
That works well. In that case there would be 5 8x8 strips, each on its own pin.
You posted no code, so the below is sketchy <— see what I did there? and makes lots of assumptions and is untested, but the ideas should be obvious:
void mySetPixelColor(int theVirtualPixel, unsigned long theColor)
{
int theStrip = theVirtualPixel / 64;
int thePixel = theVirtualPixel - 64 * theStrip;
switch (theStrip) {
case 0 :
realStrip0.setPoxelColor(thePixel, theColor):
break;
case 1 :
realStrip1.setPoxelColor(thePixel, theColor):
break;
/// and so forth for the remaining 3 strips
}
}
When you would strip.show() (haha, strip show) elsewhere, you’d have to .show all five strips.
You could set a flag to indicate that a real strip has been written to, then the strip shows could be skipped if no pixels had changed. That might save some time depending on what you are actually doing with the entire combined display.
The switch/case could be an if/else chain, but this is what switch/case is good at if you haven’t used them.
Better: put the 5 real strips into an array of strip objects, then you can write it like
myStripArray[theStrip].setPixelColor(the Poxel, theColor);
without the trouble and repetitive code that shows up in the switch/case code, that’s what arrays are for; If you haven’t used them before now woukd be a good time to learn up on them.
a7
I think the Adafruit_NeoMatrix library will do that. See the 'tiletest' example that comes with that library.
OK, so my response was off target as much fun as it was to write.
Pre stimulant beverage.
So def the library can help, but you use the word yourself that is a solution if you want to do it yourself.
A map is just an array of values that takes a virtual pixel number and returns a physical pixel number.
Or a jumble of logic that works out the flip and flop to reverse, rotate or otherwise rearrange reality.
And account for how a matrix is configured lexical or serpentine.
Here it makes sense to use the library or logic instead of an array, which used simply would be an array of 320 uh oh integers…
int map[320] = {0,1,2,3,4,5,6,7,64,65,66,67,68,69,70,71,128,129,130,131…
Time to see how Adafruit_NeoMatrix does this w/o a large simple map. Clever maths, no need to reinvent the wheel but I wanna see it for myself. It would also inform a preprocessing step where the map is created externally ahead of time and cut/pasted into the code.
Speed is probably not a large issue, but the big map array would be the very fastest at the expense of probably the most memory used.
a7
Gotta love the internets, github, Lady Ada &c.
is some logic hair and maths, not too bad at all, take a look.
a7
Alto777 I think you're onto something with int map[320]! Because each 8x8 matrix is zigzag I see this approach as the most straight forward one and yes, I do need to get all the numbers in first.
Thank you very much for your guidance.
With a table that big you may want to check out moving it into PROGMEM.
Also, I won’t be able to resist seeing if the code in Adafruit_NeoMatrix couldn’t be hacked so it would be tricked into writing the table (map) values.
I’d rather waste all day getting a program to do the work than simply sit for the 12 minutes it might take to just scratch them out manually.
As a general idea, moving to a table can be an effective way to speed up code, and it is often fun (!) to make the very last time the code the table is to replace be making the code write the table.
I usually leave the code that generates a table in the program, commented out (or rely on it being optimized out as unused), for the convenience of anyone who wants to see where the table values came from or modify/extend the table in any way.
a7
It is a lot simpler than the replies here imply.
You only need to use a look up table if the input or output is disordered. In this situation there is a mathematical relationship between the number you want and the numbers you have. So all you have to do is to write a line or two that implements that relationship.
To help you you have the modulus function by using the symbol % this performs a division function but throws away the result and leaves the remainder. Also the division operator / when dealing with integers gives you the result and throws away the remainder.
So you have the X and Y values you want to light up and you need a physical LED number that represents that LED. You have five displays so for each value of Y you have 5 * 8 = 40 LEDs. Then for each value of X you have (X / 8 ) * 8 +( X % 8) LEDs. So the led number you want is the sum of those two values.
That is for a non serpentine raster ( not zig zagging )
As you seem to have a serpentine raster you simple decide if the Y is odd or even, looking at the least significant bit of Y will tell you, ( Y & 1 will return 0 for even values ) and if it is odd subtract the result of the modules operation from 8, and if even leave it alone.
Yes, all of which can be found operating in the Adafruit_NeoMatrix library.
One thing I noticed in my low level flight about that code was this line
y = y - (major * matrixHeight); // (-* is less math than modulo)
so keep an eye out for being able to not use the % operator, for fun if nothing else.
Obvsly there are big wins if the panels are 8x8 or any power of 2 as any multiplication and division in the algorithm can be done with bit shifts and will be with modern compilers.
And I don’t mean to point it out like it is a secret, but the serpentine or zig zag wiring uses a test of the bottom bit to decide whether we on an even or odd row:
if (major & 1) {
The whole thing is worth a read, not a huge amount of code at all and plenty commented.
All that said, I have an obsession with tables and the automatic making of them, and will usually choose to use one when where I can. At the expense of the versatility that not doing affords, in, for example, code meant to be used by many who might bring differently wired matrix panels to the show.
One thing the library won’t do that a table would, besides always being faster, is to facilitate the use of several different panels either dimensional or lexical/serpentine layout.
And it would be easy to use multiple tables to achieve mirror and rotational transformations on the fly, although of course this could be done mathematically in concert with one table to get the virtual matrix behaving first.
In general, tables or maps should be in you toolkit, they can solve all kindsa problems that might otherwise take some changes IRL, not least of which woukd be having wired up something all wrong.
I never had to do that, no.
a7
You need to look in a library for that?
Agreed bit knowing when. Not to use a look up table is also good.
I used to do look up tables in my lecturers for under graduates.
There are four types classed according to the way the input and outputs are formed as ordered, a sequence of numbers the simplest being n, n+1, n+2 or so on. And disordered no simple connection like the the segments needed to light up a seven segment display.
-
orders input disordered output - drive the table by putting the input as the input as the index variable and reading the output from the array.
-
disordered input orders output - create the table as for method 1, and drive the table by searching the array that contains the value you are looking for.
-
disordered input, disordered output - create two arrays one to convert the input into an order drive like method 1, then use the output like method 2 on another array. Or use a double entry array where input and output are next to each other then drive by searching for the array for the input and the output is in the next index to it.
-
orders input, orders output - don't use a look up table at all but write a function that converts one to another.
By the way I worked it all out myself because those were the days when there were no books on the subject.
No, no I don’t.
But it’s all there, in a well done manner, as code, not prosaically presented by from some random guy on a forum.
Which it would have been if I’d gone into any detail when I mentioned mathematical approaches upthread.
Full working code is the best place to see exactly how to do something, if not always the best place to seek an explanation of how it is being done.
a7
But that code is generalised and so has to take into account of all sorts of things that is not needed.
In this case I suspect the lack of the modulus operation is because this operator works differently in python than in C, and a lot of Adafruit software is written for both.
By the way I am not some random bloke on the internet, I am Grumpy_Mike.
I wish I knew math. Never understood algebra and pretty much failed math problems. So I'm trying to wrap my head around mapping for Arduino. Let me present my scenario:
Imagine this matrix setup: 3 8x8 zigzag matrices.
xxxxxxxx xxxxxxxx The corner matrix needs to merge with the bottom matrix with a 45 degree
xxxxxxxx xxxxxxxx angle so that displays seem to wrap around the corner. Each matrix (upper
xxxxxxxx xxxxxxxx left corner) is the 0 (zero) position and bottom right is the 64th position.
xxxxxxxx xxxxxxxx Because of the zigzag nature of these matrices I haven't yet figured out how
xxxxxxxx xxxxxxxx to actually do this. I've tried creating maps, 0,1,2,3,4,5,6,7,65,66,67,68,69,70
xxxxxxxx xxxxxxxx 71. 128,129,etc. across the top to no avail. Anyone? If you need more info
xxxxxxxx xxxxxxxx please ask and I will offer.
xxxxxxxx xxxxxxxx
xxxxxxxx When I save this text this section of matrix (x's) gets shoved over to the left
xxxxxxxx it is not on the left. It is on the right below the second matrix. Just for
xxxxxxxx clarity.
xxxxxxxx
xxxxxxxx
xxxxxxxx
xxxxxxxx
xxxxxxxx
Yes full working code is what I'm trying to use. I found the sketch I needed using a mapping tutorial but it was only for LED strips, not matrices, which can be considered a long serpentine (zigzag) strip.
Zigzag matrices start out at 0 and end up at 63 then the next matrix picks up at 64 to 127 etc. Everything I've encountered while searching for a mapping solution fails to address this issue.
Hello
See this example : Adafruit_NeoMatrix/tiletest.ino at master · adafruit/Adafruit_NeoMatrix · GitHub
Also this library may be useful GitHub - Jorgen-VikingGod/LEDMatrix: FastLED Flexible Matrix Class
Thank you for this. I'm baffled and here's why. NEO_TILE_TOP+NEO_TILE_LEFT is one matrix? NEO_TILE_ROWS is the 2nd matrix? NEO_TILE_PROGRESSIVE is the tile at the end of the row that will visually rotate down? Then why NEO_MATRIX_TOP+NEO_MATARIX_LEFT? Do I just repeat twice using TILE then MATRIX?
Very confusing to me and I'm just trying to deal with 5 tiles. Can't they just be named 1 through 5 instead? Are there any pictures anywhere to be found. A picture is worth a thousand words you know.
Trying here. Put in all data and immediately got the error: "NEO_TILE" was not declared in this scope. Okay? This sketch seems bogus and not helpful.
Still seeking.
It is not bogus, it is just that you don't understand it. But without any maths skills or programming skills you are going to have a hard job of it.
Has this changed from the first one you told us about. I can't understand what you want from this post.
A map is straight ahead even if it offends some random ppl. You attempt may have failed at least because
Top left corner is pixel #1, bottom pixel is #64.
pixel numbers start at 0, so you shoukd be saying
Top left corner is pixel #0, bottom pixel is #63.
But the library approach should be straight ahead also.
Try tiletest.ino again. Linked above.
Did you install the library that it needs?
OK.
Worry only about getting it to function at all.
Change only, for now, these:
// Parameter 1 = width of EACH NEOPIXEL MATRIX (not total display)
// Parameter 2 = height of each matrix
// Parameter 3 = number of matrices arranged horizontally
// Parameter 4 = number of matrices arranged vertically
// Parameter 5 = pin number (most are valid)
So… you have 8 wide, 8 high, 5 horizontally and 1 vertically and have wired the first matrix to some pin, let’s say you’ve used pin 6.
Wire them in a daisy chain, that is the data out from the first matrix goes to the data in of the second, the data out of the second goes into the data in of the third and so forth.
Tell us you’ve got that working and we can fix up the rest of the parameters to take care of top left progressive zig zag serpentine and all those subtleties.
Actually, once you’ve wired them and connected to a pin, any neopixel demo could be run, forget if you gotten anything at all to show, perhaps start with the simplest example, where all you need to change is the number of pixels and the pin you’ve connected the first one into.
a7
I think you need to configure your tiling:
NEO_TILE_RIGHT //< First tile is at right of matrix
and
NEO_TILE_ROWS //< Tiles ordered in rows
That should give you a 2x2 tiling with the first matrix in the top right, the second in the top left, and the third in the bottom right. Wire them in that order and I think you will get the layout you want.