juj / fbcp-ili9341

A blazing fast display driver for SPI-based LCD displays for Raspberry Pi A, B, 2, 3, 4 and Zero
MIT License
1.6k stars 266 forks source link

ili9486L SPI screen will not initialize #11

Closed Trekintosh closed 6 years ago

Trekintosh commented 6 years ago

Hello,

I recently bought this screen from Aliexpress: https://www.aliexpress.com/item/3-5-inch-8P-SPI-TFT-LCD-Color-Screen-Module-ILI9486-Drive-IC-320-480-RGB/32828284227.html

I wired it up to my Pi Zero W as follows (Raspberry Pi Pins, not GPIO): GND >20 VCC>17 CLK>23 MOS>21 RES>22 DC>18 BLK>12 MIS>21

I cmake-ed fbcp-ili9341 with the following options: -DPI-ZERO=ON -DWAVESHARE35B_ILI9486=ON -DUSE_DMA_TRANSFERS=OFF -DSPI_BUS_CLOCK_DIVISOR=14 -DGPIO_TFT_RESET_PIN=25 -DGPIO_TFT_DATA_CONTROL=24

Using make-j after cmake-ing it with DILI9486=ON gave me a myriad of errors so I used the waveshare display flag instead.

When running sudo ./fbcp-ili9431, it seems to go through some initialization setup, and then stops giving further info, but the entire time the Pi has been plugged in, the screen has done nothing but shown a flat white display. It does not flicker when running ./fbcp-ili9431. I have made sure that the spi dtoverlay is commented out on my config.txt, and my core_freq is 400.

juj commented 6 years ago

Using make-j after cmake-ing it with DILI9486=ON gave me a myriad of errors so I used the waveshare display flag instead.

Thanks for reporting. Fixed in above commit so that

cmake -DILI9486=ON -DUSE_DMA_TRANSFERS=OFF -DSPI_BUS_CLOCK_DIVISOR=14 -DGPIO_TFT_RESET_PIN=25 -DGPIO_TFT_DATA_CONTROL=24 ..

should now also build.

juj commented 6 years ago

I wired it up to my Pi Zero W as follows (Raspberry Pi Pins, not GPIO): GND >20 VCC>17 CLK>23 MOS>21 RES>22 DC>18 BLK>12 MIS>21

Both MOS>21 and MIS>21? Probably a typo? MIS should be good to go to Pi pin 21, MOS should go to pin 19.

VCC>17

Double-checking: Pin 17 is a 3.3V pin. Do you know if the display operates on 3.3 volts power and not on 5 volts? (don't plug it in 5 volts to just to try, if it's 3.3V it can burn if connected wrongly to 5V) Many of my displays plug in to 5 volts for power, although those are Adafruit ones so they often go interchangeably with either of 3.3V or 5V.

ILI9486L and ILI9486 should to my understanding work interchangeably. Their controllers should be the same, except that ILI9486L strips out unneeded support for MIPI DSI that is not used with SPI. So the rest of your setup looks good.

juj commented 6 years ago

Paired my WaveShare 3.5" (B) ILI9486 display to a Pi Zero W, a combination that I have not tried before; and found a race condition that caused the display to randomly fail to initialize when DMA was enabled. That is now fixed in above commit, try git pulling to latest for the fix. Not sure if that might help when DMA is disabled, fingers crossed.

Trekintosh commented 6 years ago

Okay, I did it again, this time with pictures. Firstly here's the wiring: https://puu.sh/ADWWv/021ce8c3cc.JPG https://puu.sh/ADWX0/5b70f34f32.JPG https://puu.sh/ADWXq/2ae22a19e6.JPG

After making it with cmake settings -DPI_ZERO=ON -DILI9486=ON, DSPI_BUS_CLOCK_DIVISOR=14 -DGPIO_TFT_DATA_CONTROL=24 -DGPIO_TFT_RESET_PIN=25 -DUSE_DMA_TRANSFERS_OFF .. I then ran it, and here is a picture (apologies, I didn't do this in SSH and don't have a capture card) of what it showed me. However, the screen stayed white the entire time.

https://puu.sh/ADWQz/fb34f4ff23.JPG

You were correct, I did make a typo in the initial post.

Also as best as I could make out from the datasheet, the LCD+controllers are 3.3v, and the pcb is entirely passives, no regulator I could see. I don't think it's a 5v lCD.

juj commented 6 years ago

Not quite sure, everything looks good to me. Tested out on my WaveShare 3.5" (B) display and Pi Zero W, with

cmake -DPI_ZERO=ON -DILI9486=ON -DSPI_BUS_CLOCK_DIVISOR=14 -DGPIO_TFT_DATA_CONTROL=24 -DGPIO_TFT_RESET_PIN=25 -DUSE_DMA_TRANSFERS=OFF ..

the build does work out ok.

One thing that does come to mind is that ILI9486 is a peculiar display controller since its SPI communication bus word size is 16 bits wide instead of the usual 8 bits I see on every other controller. ILI9486 is also the only controller I have met that has MIPI DSI support.

Since ILI9486L removes the MIPI DSI support that ILI9486 has, then perhaps ILI9486L also reverts to a 8 bits word size instead of the 16 bits on ILI9486. That is a random guess though, I cannot find a mention in the ILI9486L vs ILI9486 spec sheets to say anything about this. In any case, you can try git pulling to latest to get the above commit, and then apply the following change locally to your checkout:

diff --git a/ili9486.h b/ili9486.h
index 2471e4c..8b77bd9 100644
--- a/ili9486.h
+++ b/ili9486.h
@@ -21,7 +21,7 @@
 #endif

 // On ILI9486 the display bus commands and data are 16 bits rather than the usual 8 bits that most other controllers have.
-#define DISPLAY_SPI_BUS_IS_16BITS_WIDE
+// #define DISPLAY_SPI_BUS_IS_16BITS_WIDE

 // ILI9486 does not behave well if one sends partial commands, but must finish each command or the command does not apply
 #define MUST_SEND_FULL_CURSOR_WINDOW

i.e. comment out #define DISPLAY_SPI_BUS_IS_16BITS_WIDE to make fbcp-ili9341 drive the display with 8 bits wide word size.

If that does not help, then I'm not sure, there must then be something fundamentally different with ILI9486L and ILI9486 assuming everything else checks out properly.

Trekintosh commented 6 years ago

This has produced some sort of progress!

First here is the pictures (again, sorry) of the CMake and Make results https://puu.sh/AE19Y/752a31d9ec.JPG https://puu.sh/AE1bn/b650e48d81.JPG

When starting the ./fbcp-ili9341, the screen goes from flat white to what appears to be every other line being black. Here are two pictures of the full white, then the white/black stripes. Apologies for blurriness and screen door effect. My phone was really struggling to get this close up.

https://puu.sh/AE1f2/ab3c01befd.JPG https://puu.sh/AE1fw/61776dc62f.JPG

This is identical to the behavior I was getting when attempting to use fbtft_device's custom ili9486 device profile.

juj commented 6 years ago

That is indeed promising, and I think it confirms that the display is 8 bits in word size instead of 16 bits that ILI9486 is. So the differences are more than just stripped down MIPI DSI support.

My WaveShare 3.5" (B) display does the same - its "reset state" is the kind of alternating "every other scanline = white, every other scanline = black" striped pattern. That occurs after this line has finished: https://github.com/juj/fbcp-ili9341/blob/master/ili9486.cpp#L126

This suggests that the initialization commands do reach the display, but that ILI9486ClearScreen() function does not go correctly through at https://github.com/juj/fbcp-ili9341/blob/master/ili9486.cpp#L128. It might be that it is taking in commands, but is not accepting pixel data.

Had a read through the ILI9486 and ILI9486L spec sheets side by side, and added explicitly in the initialization different commands in the spec sheets that might have an effect. If the above changes do not help, then I am at a loss, and I think the only way might then be to reverse engineer a working driver if such exists, or try random changes to the initialization routines reading against the ILI9486L spec sheet to see if anything there can bring reaction to the display. Either way may be a bit of a challenge, sorry I am not able to be of better help here.

Trekintosh commented 6 years ago

Sorry for lack of clarity on my part. You mention you "added explicitly in the initialization different commands in the spec sheets that might have an effect," does that mean you updated the Git and I should try a new pull and make, etc and see if it works for my display?

juj commented 6 years ago

Yeah sorry, what I meant is that I pushed a new commit in https://github.com/juj/fbcp-ili9341/commit/ada111e3ed0e69144d483efcc5f1df091a6a7197 that you can git pull to try out, if that might make any difference.

If that does not help, then it is possible that the issue is in some other difference in required initialization, and you can try following the similar kind of approach in that commit to modify the initialization sequence, to try to see if you can make the display react to something. The spec sheet I was reading is this ILI9486L V0.06.pdf.

juj commented 6 years ago

Something that is also worth occassionally trying out when doing multiple changes, is to physically power off the Pi and the display after a failed attempt. I do find that sometimes when I run a command sequence to a display that it does not understand, it gets out of sync or somehow else in an odd state, and I need to hard power it off to reset it.

Trekintosh commented 6 years ago

After downloading the new commit, I ran the script and got some extremely strange behavior.

https://youtu.be/OKulcCcZt0g

The screen started white then slowly dimmed until it was a dark grey smear, with the bottommost (pin side) section being lighter, before it too fades leaving the bottommost two pixels in full brightness. The greyness seems to have vertical striations as well, though that could just be my screen protector. The process repeats if I run the script again.

Trekintosh commented 6 years ago

Interestingly, if I power cycle the screen(by pulling ground) while the script is running, it stays as it was when last powered on. E.G. if I power cycle it midway through fading, it comes back in the same part of fading and continues to fade. If I stop the script, the screen maintains its state, unless I power cycle it, in which case it goes back to being fully white.

juj commented 6 years ago

That is interesting. I believe what is happening here is that the display stopped refreshing its pixels across full height ,so they fade out slowly after time. (LCD pixels need constant refreshing)

This is definitely not the desired result, but it does confirm that the display did react to the commands that were specified to it. Most likely the command that caused the artifact on video is this line: https://github.com/juj/fbcp-ili9341/commit/ada111e3ed0e69144d483efcc5f1df091a6a7197#diff-497750249aed12e322610c93513785b6R126 which attempts to initialize the display to its normal height of 480 pixels. You can try commenting out that line (or any other line that was added) one by one (then remake and rerun) to find which caused this effect. (you'll want to revert that out)

To try to find a suitable initialization sequence for the display, you could see if something in http://aitendo3.sakura.ne.jp/aitendo_data/product_img/lcd/tft2/Z350IT002/ILI9486AN_V0.6.pdf could be adaptable. In there, a sequence

LCD_ILI9486_CMD(0xC5); 
LCD_ILI9486_INDEX(0x00); 
LCD_ILI9486_INDEX(0x55);

translates to a sequence

SPI_TRANSFER(0xC5, 0x00, 0x55);

in fbcp-ili9341 initialization. That application notes pdf is not for ILI9486L but it is for ILI9486, although for some reason it lists multiple variants, and some of the commands are undocumented in the ILI9486 spec sheet pdf file above, so perhaps with some luck something there might give good results.

Although this can be quite a trial and error attempt, so patience and free time is good to prepare with if you want to go that route.

juj commented 6 years ago

Also for reference, here are the contents of my full /boot/config.txt that I am running with on Pi Zero W + WaveShare 3.5" (B):

hdmi_group=2
hdmi_mode=87
hdmi_cvt=480 320 60 1 0 0 0
hdmi_force_hotplug=1

i.e. there are no other lines. I SSH in to the Pi via network to configure and build fbcp-ili9341. May be good to double check that your /boot/config.txt does not have any extra directives with dtoverlay= or dtparam= that might be leftovers.

(Although usually I do recall if I did have some bad /boot/config.txt options, I would still always be able to clear the screen to black before the conflicting dtparam/dtoverlay directives would have time to interfere with fbcp-ili9341, so not sure if /boot/config.txt directives can be at fault here)

Trekintosh commented 6 years ago

I did get some information from the seller before I ordered the display, including what appears to be some initialization code. Can you tell me if this matches up to what you have for initialization on this display already?

`void Initial_ILI9486() { //**** Reset LCD Driver****// RES=1; Delayms(20); RES=0; Delayms(60); RES=1; Delayms(120); //***** Start Initial Sequence**// comm_out(0XF2); data_out(0x18); data_out(0xA3); data_out(0x12); data_out(0x02); data_out(0XB2); data_out(0x12); data_out(0xFF); data_out(0x10); data_out(0x00); comm_out(0XF8); data_out(0x21); data_out(0x04); comm_out(0XF9); data_out(0x00); data_out(0x08); comm_out(0x36); data_out(0x08); comm_out(0x3A); data_out(0x05); comm_out(0xB4); data_out(0x01);//0x00 comm_out(0xB6); data_out(0x02); data_out(0x22); comm_out(0xC1); data_out(0x41); comm_out(0xC5); data_out(0x00); data_out(0x07);//0X18 comm_out(0xE0); data_out(0x0F); data_out(0x1F); data_out(0x1C); data_out(0x0C); data_out(0x0F); data_out(0x08); data_out(0x48); data_out(0x98); data_out(0x37); data_out(0x0A); data_out(0x13); data_out(0x04); data_out(0x11); data_out(0x0D); data_out(0x00); comm_out(0xE1); data_out(0x0F); data_out(0x32); data_out(0x2E); data_out(0x0B); data_out(0x0D); data_out(0x05); data_out(0x47); data_out(0x75); data_out(0x37); data_out(0x06); data_out(0x10); data_out(0x03); data_out(0x24); data_out(0x20); data_out(0x00); comm_out(0x11); Delayms(120); comm_out(0x29);

}`

Trekintosh commented 6 years ago

However it seems that all information the seller sent me is for the ili9486, not the ili9486L, so I'm unsure if it is helpful.

Trekintosh commented 6 years ago

I just noticed a mistake on my part. When I made the file that I used for the video of the weird behavior, I neglected to comment out the bus width in ili9486.h locally again. When I do comment it out and make again, I return to the previous initialization mode of alternating black and white rows on the screen. When the script is ctrl+c'd, the screen returns to full white, and comes back to alternating lines when run again.

I apologize if I sent you down any rabbit holes.

juj commented 6 years ago

That set of initialization strings would be encoded as

    SPI_TRANSFER(0XF2, 0x18, 0xA3, 0x12, 0x02, 0XB2, 0x12, 0xFF, 0x10, 0x00);
    SPI_TRANSFER(0XF8, 0x21, 0x04);
    SPI_TRANSFER(0XF9, 0x00, 0x08);
    SPI_TRANSFER(0x36, 0x08);
    SPI_TRANSFER(0x3A, 0x05);
    SPI_TRANSFER(0xB4, 0x01//0x00);
    SPI_TRANSFER(0xB6, 0x02, 0x22);
    SPI_TRANSFER(0xC1, 0x41);
    SPI_TRANSFER(0xC5, 0x00, 0x07//0X18);
    SPI_TRANSFER(0xE0, 0x0F, 0x1F, 0x1C, 0x0C, 0x0F, 0x08, 0x48, 0x98, 0x37, 0x0A, 0x13, 0x04, 0x11, 0x0D, 0x00);
    SPI_TRANSFER(0xE1, 0x0F, 0x32, 0x2E, 0x0B, 0x0D, 0x05, 0x47, 0x75, 0x37, 0x06, 0x10, 0x03, 0x24, 0x20, 0x00);
    SPI_TRANSFER(0x11);
    usleep(120*1000);
    SPI_TRANSFER(0x29);

in fbcp-ili9341.

juj commented 6 years ago

Applying the above set of initialization would look something like https://gist.github.com/juj/a16603dc6cf6aacceac95de2b3f35a81 . You can try that file instead to see how it behaves.

Trekintosh commented 6 years ago

Okay, to use that file do I need to do anything special, or just another regular pull request?

juj commented 6 years ago

Copy paste the file (or just its contents) to replace the original ili9346.cpp in your working directory. I did not want to push that directly to the repository to not fill up the tree with temporary debugging attempts code.

If you are on a Pi Zero itself without a text editor, you can do

wget https://gist.githubusercontent.com/juj/a16603dc6cf6aacceac95de2b3f35a81/raw/19a7f25902e63fe77098449ffa89ec8265daf594/ili9486.cpp

directly on the Pi terminal to download the file to local disk.

Trekintosh commented 6 years ago

Thank you for preparing the file for me. I dropped it in, re cmade and re make'd, and the behavior is still the white + black lines initialization behavior. I'm not sure where else to go at this point besides trying the trial+error method to reverse engineer it like you described.

Thank you for all the help you've given me. I will update this if and when I find something.

Trekintosh commented 6 years ago

After having done some experimentation, I cannot seem to find any rhyme or reason to how the display behaves. If you like, I can mail you the display to have (I have no use for it if it doesn't work) and that way you can figure out how to get a 9486L working on your own time.

juj commented 6 years ago

Sorry to hear. :/ Some searching on the web about the display about ILI98486L specifically does not find much, ended up with these:

Curiously the last link has a comment "HIMAX HX8347 LCD controllers driver", perhaps a leftover, or used interchangeably? Another page at https://www.raspberrypi.org/forums/viewtopic.php?t=57548#p440798 has a reference to batches of a display coming with "ILI9486L and HX8357", which might mean there's some level of compatibility.

You could try seeing what happens if the display is driven with fbcp-ili9341s HX8357D path, with

cmake -DHX8357D=ON -DUSE_DMA_TRANSFERS=OFF -DSPI_BUS_CLOCK_DIVISOR=14 -DGPIO_TFT_RESET_PIN=25 -DGPIO_TFT_DATA_CONTROL=24 ..

It is a very kind offer to send the display over to me, though it might not be worth the exercise if you are located outside Europe. I reside in Helsinki in Finland, and e.g. a Priority Mail International® Small Flat Rate Box via USPS seems to be $32.25 if you are located in the US. If the value of the display is around $20, it is just around the magic limit that Finnish customs may ask me to declare it upon receival for VAT and import taxes. If you are in Europe, then it will be simpler. You can reach me at posti if you'd like to coordinate further.

IndianBoy42 commented 6 years ago

Hello! Just chiming in to say I've been having this same problem (although not on the RasPi but on an stm32f4, and on my own written library), and just managed to figure it out.

Basically the problem is the ILI9486L only supports 18bits/pixel or RGB666 (or RGB111, but importantly not RGB565 or RGB888) mode over 4 wire SPI, so for me, at initialization CMD:0x31 DAT:0x55 has to be changed to 0x66, and when sending the pixels you have to send 3 bytes with the R, G and B components in the 6 most significant bits of each byte (see: https://www.displayfuture.com/Display/datasheet/controller/ILI9486L.pdf pg48)

After that it should work, hope this helps you guys :)

juj commented 6 years ago

img_20180702_192000

Thanks @IndianBoy42 ! Pretty amazing timing, I just got an ILI9486L display in mail to play with myself. Confirmed that R5G6B5 mode is what caused the display not to react, and in R6G6B6 mode it works. You saved me a lot of time! Added support for ILI9486L now, enabled by passing -DILI9486L=ON in CMake, see details in https://github.com/juj/fbcp-ili9341/commit/378d111d00a5996f7039630f5c607d3cdada34e0.

Trekintosh commented 6 years ago

Tested on my ili9486L display (same model as Juj’s) and it works a treat. Performance is marginally better than the Waveshare 35b. Running cmatrix in the terminal yields about 8-13fps with a frame rate target of 20 and single rectangular diff and 180 degree flip enabled. Cmatrix in a lxtermjnal window in i3 yields about 13-19fps, an excellent improvement.

d23d0d15-867a-436d-8629-d1a637ac830f 01cf89a4-125b-4457-b0e5-3adc011e4be4

The screen flip seems to yield a ~1-2% cpu increase but that’s within reason.

I have to say this little display is excellent. I don’t think it’s IPS, but the viewing angles are superb compared to my UCTRONICS 3.5” display.

juj commented 6 years ago

Haha, cmatrix looks pretty cool, had not seen that project before :)

Running cmatrix from command line (not inside X windowing system) on a Pi 3B gives fbcp-ili9341 CPU usage that fluctuates between 15.3% and 27.9%, and frame rate of 24p-27p with no frames lost. cmatrix itself consumes about 4.6% of CPU. Pi Zero definitely has a harder time with this since it's limited to a single core approach, but the numbers you posted don't look at all bad there either.

Trekintosh commented 6 years ago

Indeed, I was impressed with the zero. I specifically chose cmatrix because I knew it would generate large single rectangles of movement. I didn't try it with full diffing.

MarkCWallis commented 5 years ago

IndianBoy42 you saved me, thank you. I don't even know if I have an L model controller or not but it is now working because of reading your comment better than I read the datasheet! Of interest is that b6h command should have three parameters not two as in most init examples I see. If I use b6,08,82,27 I get a 2/3 partial screen which fades from dark to light. If I skip b6h it works great.

VeteranGamer commented 5 years ago

Hi, I've got a 3.5" Waveshare Spotpear (A) V3 I've tried to enable it using -DILI9486L=ON

but no success

my cmake is cmake -DSPI_BUS_CLOCK_DIVISOR=12 -DILI9486L=ON -DARMV8A=ON -DGPIO_TFT_DATA_CONTROL=24 -DGPIO_TFT_RESET_PIN=25 -DSTATISTICS=0 -DDISPLAY_ROTATE_180_DEGREES=ON ..

Pi3A+

any tips on how I should proceed

Thank you

.

robbycandra commented 5 years ago

That set of initialization strings would be encoded as

    SPI_TRANSFER(0XF2, 0x18, 0xA3, 0x12, 0x02, 0XB2, 0x12, 0xFF, 0x10, 0x00);
    SPI_TRANSFER(0XF8, 0x21, 0x04);
    SPI_TRANSFER(0XF9, 0x00, 0x08);
    SPI_TRANSFER(0x36, 0x08);
    SPI_TRANSFER(0x3A, 0x05);
    SPI_TRANSFER(0xB4, 0x01//0x00);
    SPI_TRANSFER(0xB6, 0x02, 0x22);
    SPI_TRANSFER(0xC1, 0x41);
    SPI_TRANSFER(0xC5, 0x00, 0x07//0X18);
    SPI_TRANSFER(0xE0, 0x0F, 0x1F, 0x1C, 0x0C, 0x0F, 0x08, 0x48, 0x98, 0x37, 0x0A, 0x13, 0x04, 0x11, 0x0D, 0x00);
    SPI_TRANSFER(0xE1, 0x0F, 0x32, 0x2E, 0x0B, 0x0D, 0x05, 0x47, 0x75, 0x37, 0x06, 0x10, 0x03, 0x24, 0x20, 0x00);
    SPI_TRANSFER(0x11);
    usleep(120*1000);
    SPI_TRANSFER(0x29);

in fbcp-ili9341.

I try this Init Code, and found that it works OK.