letscontrolit / ESPEasy

Easy MultiSensor device based on ESP8266/ESP32
http://www.espeasy.com
Other
3.23k stars 2.2k forks source link

Brainstorming NeoPixel with 8x8 Display #3958

Closed fly74 closed 2 years ago

fly74 commented 2 years ago

As like in issue discussed, we could make this display more usable when we could put some pixel map to the flash to use it easily from rule to show maybe arrow, stop or other signs.

@TD-er @tonhuisman

fly74 commented 2 years ago

Or maybe a charset implementation like in the 7 segment display.

tonhuisman commented 2 years ago

Well, there is the challenge of custom matrix sizes. I know there are standard 'slabs' with 8x8 up to at least 16x32 and 8x64 NeoPixels, but you can of course configure to your own preference.

fly74 commented 2 years ago

But it's alway a factor of 8. so we could make it for 8x8 and scale for other sizes.

fly74 commented 2 years ago

https://user-images.githubusercontent.com/38754941/154747321-86c1594f-5afe-42f9-b3e0-55e053e5c097.MOV

An example

tonhuisman commented 2 years ago

I've been investigating this a bit, and found this rather extensive (commercial) ΓΌber-guide to NeoPixels in several forms and shapes. For the matrix form factors I am thinking about adding a separate plugin, that I'd expect to use the AdaFruit NeoMatrix library, as that seems the most appropriate (read: time-saving πŸ˜‰).

I'll probably end up with a somewhat similar, though much less complex, configuration like I did for P104 - Display - MAX7219 dot matrix, except that there will be only 1 zone. I'm not sure (didn't investigate that yet) if scrolling text is an available option, or I might need to add that. Image support can be a bit challenging, as that's not yet implemented in ESPEasy, but would be a really welcome addition for other display types as well, as the AdaFruit GFX library has support for that, and that is used by the NeoMatrix and most graphic displays supported by ESPEasy.

fly74 commented 2 years ago

I don't know if we can use a binary part of the flash to store 3byte x 64 (and other sizes) as a picture. Maybe classical files in flash as the config for example.

Text scrolling would be nice too.

tonhuisman commented 2 years ago

ESPEasy does use a file-system, and you can upload any type of file there, but there are limits on available space, though, depending on the configuration used (128 kB for 1M Flash devices up to ~8 MB on the MAX 16M8M ESP32 configuration), and they all use somewhere between 64 kB and 200 kB (depending on the number of tasks, and size of rules files) for storing the configuration, so that has to be subtracted. And then some free space is required to be able to overwrite an existing file during config save.

TL;DR: Image files should be read from the file-system, indeed.

tonhuisman commented 2 years ago

I've reserved plugin ID P131 for this plugin, no ETA though πŸ˜ƒ

fly74 commented 2 years ago

Size is very small 8x8x64 = 192 byte for an rgb picture is not so much.

fly74 commented 2 years ago

File format could be BMP ,it's uncompressed and maybe easy to assign to the pixels.

TD-er commented 2 years ago

Size is very small 8x8x64 = 192 byte for an rgb picture is not so much.

For a single standalone "picture" it's not much, but I guess you may want a bit more flexibility here in what to show :) Support for 2D pixel displays tend to get large very quickly. Adding color does speed this up even more.

fly74 commented 2 years ago

Is it possible to make plugin only available for ESP32 or 4M devices?

To load pictures via HTTP from a server would be nice too. So we don't have to save them on the device.

tonhuisman commented 2 years ago

8x8x64 = ~192~ 4096

Well, my calculator says that result is 4096, but the real calculation should be 8x8x(24/8) = ~1536~ 192, as each (neo)pixel supports 24 bit colors, so it would be feasible to use 24 bit BMP files. The Adafruit GFX library reduces that to 16 bits, btw, as the standard supported TFT displays only support up to 65535 colors (RGB565 coded), and converts the colors to RGB565 when reading such file.

Edit: Corrected for bit/byte mix-up πŸ˜…

TD-er commented 2 years ago

Well, my calculator says that result is 4096, but the real calculation should be 8x8x24 = 1536, as each (neo)pixel supports 24 bit colors, so it would be feasible to use 24 bit BMP files.

Bits ;) 24 bit = 3 bytes => 8x8x3 = 192 bytes

fly74 commented 2 years ago

8x8x64 = ~192~ 4096

Well, my calculator says that result is 4096, but the real calculation should be 8x8x24 = 1536, as each (neo)pixel supports 24 bit colors, so it would be feasible to use 24 bit BMP files.

The Adafruit GFX library reduces that to 16 bits, btw, as the standard supported TFT displays only support up to 65535 colors (RGB565 coded), and converts the colors to RGB565 when reading such file.

You mix up bytes and bit. 24 bit= 3 byte πŸ˜…

tonhuisman commented 2 years ago

πŸ˜…

fly74 commented 2 years ago

And I've seen some things with Neopixel flow pictures like waterfall wich move the lines up to top and things from left to right. For that we need picture 8 x X lines and need to move them with a value of speed.

tonhuisman commented 2 years ago

I think that's called a 'sprite' πŸ›Έ

fly74 commented 2 years ago

Like this at 0:42

TD-er commented 2 years ago

Hmm that looks like code that needs a lot of CPU time to run. Scrolling in 1 direction (based on the orientation and order of the LEDs) is just like adding 1 row of pixels. But scrolling in the other direction needs to repaint the entire "display". So not sure how doable this scrolling is on an ESP8266 while maintaining WiFi connection. On an ESP32 it might be doable by running it on the 2nd core, or at least as a new RTOS task.

fly74 commented 2 years ago

It's a full repaint with every line no matter what direction. Maybe it should be a version only esp32neopixelultra16M.bin πŸ˜ƒ. But scrolling is for sure not the main reason to make it.

tonhuisman commented 2 years ago

The NEOPIXEL builds are already planned/prepared in PR #3899 so I'd expect to include this one in those builds as well.

fly74 commented 2 years ago

With multiple panels in a row it's a little tricky. 2 panels 2 solutions should be an option for the orientation because, with first pixel left/bottom it would be a flow of an picture with 8x16 pixel from an bmp. With the first pixel left top, the picture must be divided in the parts of the size from one panel - if you know what I mean. with 4 panel I have no idea.

Screenshot 2022-02-25 203746

tonhuisman commented 2 years ago

Received my ordered NeoPixel matrixes (8x8 leds, 4 units), wired them up and started working on a plugin. This is a first impression of how it could look:

NeoMatrix-first-impression

(I really should have ordered an extra matrix to be able to fit ESPEasy on it 🀣) I'll implement some form of text scrolling, like done on the P073 7-segment display, and built into the library used on P104 MAX7219 Dotmatrix.

Still lots of work, and testing, to do, here is an impression of the Device configuration and its options:

Screenshot - 06_03_2022 , 20_43_56

(Many options and the entire AdafruitGFX_helper shared with P116)

fly74 commented 2 years ago

Hey looks nice. I think the interesting part would be to select an BMP from filesystem to display with an assignable brightness πŸ”†.

tonhuisman commented 2 years ago

BMP from filesystem to display

I have some ideas on how to apply that, if you have a few of those available, preferably in a .zip file to avoid tampering by github, for me to experiment with what you want to use, that would be nice.

fly74 commented 2 years ago

@tonhuisman sure here are some by me. For the arrow it would be nice have a rotation angle to display 4 directions with one bmp. The RGB values must be reduces by the brightness value to not BBQ the panel with full yellow :)

BMPs.zip

arrow_y.bmp black.bmp stop.bmp

Maybe we could limit to 8 bit pictures, I think it could be enough.

and on for 8x16 pixel 2 panels:

arrow_8x16.zip

tonhuisman commented 2 years ago

Status update: (sorry for the poor photo quality)

IMG_20220310_213559 IMG_20220310_213734 IMG_20220310_213921

So, yes, we can display (small) bmp files on these displays, and by playing with rotation and x/y coordinates, you can place them anywhere πŸ˜‰ No scaling, btw, so when configured for 16x16 pixels, you can use a 16 pixel high bmp, on an 8 bit pixel height display the image will be clipped. Code is not yet ready for prime-time, but it will be part of the AdafruitGFX_helper module I've added for P116, which implies we'll be (optionally, build-size permitting) able to display (bmp) bitmaps on TFT displays too πŸ›©οΈ And that implies that you can use the drawing and text features (doc.) (<trigger> will be neomatrix or neo) of this module on this display type πŸ˜„

fly74 commented 2 years ago

Hey @tonhuisman sounds great. Is it ready for the 90 degree version of my hand painted paper above? I have to use it because of the modules I own. They can only with this orientation used. πŸ‘

Will it be an extra bin for neopixel with only this plugin and maybe the switch plugin and only fΓΌr ESP32? Can you provide a test build?πŸ˜‰

TFT display is interesting, is there a display module wich is usable?

tonhuisman commented 2 years ago

Is it ready for the 90 degree version of my hand painted paper above?

It should be, that's why I have added all these configuration options πŸ˜‰, like Matrix start-pixel and Tile start-matrix: Screenshot - 06_03_2022 , 20_46_20 Rows/Columns mode: Screenshot - 06_03_2022 , 20_48_01 and flow-direction Screenshot - 06_03_2022 , 20_50_59

Your 90 degree drawing should have width: 8, height:8, Bottom/Left, Columns, Progressive for Matrix, and width: 2, height: 1, Top/Left, Rows, Progressive for Tile configuration. NB: All matrices must be of the same, rectangle, size, and the resulting set of tiles is always a rectangle.

All inspired by this library documentation (I'll probably add examples of that in the documentation)

I'll provide a test-build here after some more testing (and probably bug-fixing πŸ˜†)

fly74 commented 2 years ago

Do we need an option for brightness or is the rgb value the brightness for each color? Are the bmp usable in rules?πŸ€“

tonhuisman commented 2 years ago

Do we need an option for brightness or is the rgb value the brightness for each color?

For the NeoPixel Matrix displays, the neomatrixcmd,bright,<0..255> command is available, Photo's above are taken with brightness set to 20 (it was quite late and dark, so not much light needed). The default brightness is 255, and when lighting up all (neo)pixels with white, you can nearly light up a room with 1 matrix 🀣 For TFT displays the brightness is indeed controlled by the colors, but also by the backlight intensity.

Are the bmp usable in rules?πŸ€“

Yes, a new command <trigger>,bmp,<x>,<y>,<bmpfile.bmp> has been added to the AdafruitGFX_helper module, to place a bmp file with left-top position x,y (~1~ 0-based) on the display.

A few examples using images I grabbed from the i-net, shown on a ST7789 240x240 display, as supported by P116: IMG_20220311_151523 IMG_20220311_151650

And to prove I didn't just steal them from someone else, or photo-shopped them, also my avatar (80x80) dropped semi-random on the same display: IMG_20220311_151901

fly74 commented 2 years ago

@tonhuisman This is really cool. It is a I2C display right or SPI? Is 2.8inch also compatible? And the biggest?

tonhuisman commented 2 years ago

That AdafruitGFX_helper module is planned to be used for P095 (TFT) ILI9xxx, P096 (ePaper), P116 (TFT ST77xx) and P131 (this NeoPixel Matrix, that's why I've put it in the 'display' category). All plugins, bar this one, are updated to use that via PR #3761, and some extra display models in P095 via PR #3903, so the largest available resolution currently is 320x480, and possibly up to 4.7", but if you find a larger size, using any of these chips (ILI93xx/94xx or ST77xx) that should work as well. Theoretically it should be possible to build a huge NeoPixel matrix display, but I'm not sure what the max. number of neopixels, that can be connected serially, is πŸ˜‰ as there will be issues with update speed, because of all pixels being updated sequentially πŸ€”

fly74 commented 2 years ago

The default brightness is 255, and when lighting up all (neo)pixels with white, you can nearly light up a room with 1 matrix 🀣

yeah and it needs 4A with full on. Maybe we can limit the brightness by a parameter. My powersuppy don't deliver 20W :)

tonhuisman commented 2 years ago

Fixed that already, I'll upload a test build later today.

fly74 commented 2 years ago

Theoretically it should be possible to build a huge NeoPixel matrix display, but I'm not sure what the max. number of neopixels, that can be connected serially, is πŸ˜‰ as there will be issues with update speed, because of all pixels being updated sequentially πŸ€”

And a power plant!

fly74 commented 2 years ago

Theoretically it should be possible to build a huge NeoPixel matrix display, but I'm not sure what the max. number of neopixels, that can be connected serially, is πŸ˜‰ as there will be issues with update speed, because of all pixels being updated sequentially πŸ€”

And a power plant!

And let's play with numbers. If we could adress a neopixelmatrix for 8k, we need:

-8k is 7680 Γ— 4320 -devided to 960x540 panels = 518.400 panels -dimensions one panel is 65x65mm = 62,4m x 35,1m for the screen -518.400 panels needs 20W at full power each = 10MW for all ?

-4k all devided by 4 -fullhd devided by 16

but it would be impressive.

fly74 commented 2 years ago

An now the cherry. Can we load a bmp to tft as background and write text over it?

tonhuisman commented 2 years ago

An now the cherry. Can we load a bmp to tft as background and write text over it?

Yes, if you only supply the foreground color, the background will become transparent, so writing on top of an image will overlay as expected. But updating data, like time or temperature, will become a mess, as the previous content isn't overwritten, that's why a txtfull subcommand is available that also expects/applies a bg-color.

tonhuisman commented 2 years ago

This part of the device configuration is updated: Screenshot - 11_03_2022 , 19_54_29

fly74 commented 2 years ago

This part of the device configuration is updated:

Screenshot - 11_03_2022 , 19_54_29

A maximum brightness as I said would be fine to not overload the power supply by setting to high values eg. from remote.

tonhuisman commented 2 years ago

Test-builds, yay 😸

(updated, see below)

The command to display a .bmp file is: <trigger>,bmp,<x>,<y>,<filename.bmp> <trigger> can be selected in the device configuration.

Didn't add a max. setting, as that's the responsibility of the user, IMHO. Just set the initial brightness properly, and don't overload, but you should still be able to use the full range.

Images can be read from internal flash storage or from SD-card but I couldn't test that yet, as my unit with an SD reader wouldn't cooperate 😞

tonhuisman commented 2 years ago

Maybe we could limit to 8 bit pictures, I think it could be enough.

It supports 1 bit and 24 bit color depth, uncompressed BMP files. As the source that I used, Adafruit_ImageReader, does. Modified code from that library to support also non-SPI displays, and included it into AdafruitGFX_helper.

fly74 commented 2 years ago

Didn't add a max. setting, as that's the responsibility of the user, IMHO. Just set the initial brightness properly, and don't overload, but you should still be able to use the full range.

I think it's a safety reason. I build the panels in little cases which can not take the heat of 20 W at full power. If I make a mistake and send the wrong value it could be dangerous. With the limit I would feel betterπŸ€“

fly74 commented 2 years ago

@tonhuisman First test looks great, but the text it's mirrored ?!?:

IMG_1397

Screenshot 2022-03-12 095010

fly74 commented 2 years ago

Are the bmp usable in rules?πŸ€“

Yes, a new command <trigger>,bmp,<x>,<y>,<bmpfile.bmp> has been added to the AdafruitGFX_helper module, to place a bmp file with left-top position x,y (~1~ 0-based) on the display.

Worked as expected but also mirrored.

tonhuisman commented 2 years ago

To find the actual geometry you can use P038, NeoPixel (Basic), and set it to have 128 pixels, then use command neopixelline,1,12,10,10,10, that wil light up the first 12 pixels, so you can recognize how it's built. And please show a photo of that for me to understand.

NB: I did find a bug related to the Progressive/Zigzag settings, but as it is in the default Progressive setting, == 0, that can't be the cause of text being displayed mirrored. And if it is, I'd like to add that as a feature πŸ˜„ (but I did not find it in the source code...) NB2: I'll also add a setting for Max. brightness, as you have a valid use-case for that πŸ‘

tonhuisman commented 2 years ago

command neopixelline,1,12,10,10,10, that wil light up the first 12 pixels,

Should have asked a bit smarter, like:

neopixelall,0,0,0 // Turn all off
neopixel,1,20,0,0 // First pixel red
neopixelline,2,12,0,20,0 // Pixel 2..12 green
neopixelline,17,21,0,0,20 // Pixel 17..21 blue

This can be entered via the Tools/Command option, as 3 separate commands, once the NeoPixel (Basic) plugin is enabled. That can be manually enabled using taskenable,neopixel. It can be active side by side with the NeoPixel Matrix plugin, as the GPIO is only used when updating the pixels.

fly74 commented 2 years ago

To find the actual geometry you can use P038, NeoPixel (Basic), and set it to have 128 pixels, then use command neopixelline,1,12,10,10,10, that wil light up the first 12 pixels, so you can recognize how it's built. And please show a photo of that for me to understand.

These are 2 separate 8x8 panels.

Commands:

neopixelline,1,12,10,10,10 neopixelline,65,76,10,10,10

look like this:

IMG_1398