mcufriend shield 0x4535 слабая яркость
- Войдите на сайт для отправки комментариев
Сб, 27/08/2016 - 01:30
Здравствуйте, прошу помощи. Приехал ко мне китайский дисплей+тач шилд, воткнул его в ардуину, склепал скетч фоторамки, работает - но картинки выводятся с очень низкой яркостью (гаммой?). Но если нажать ресет, то в течение следующей секунды бесхозный дисплей без мастера отображает эту картинку с нормальной яркостью. Есть подозрение, что такое поведение у дисплея из-за подключенной sd-карты, пока скетч побайтово читает картинку с неё, экран сильно мерцает. Подскажите плиз, что делать, куда копать?
001 | #include <Adafruit_GFX.h> // Core graphics library |
002 | #include <AdaLGDP4535TFTLCD.h> // Hardware-specific library |
003 | #include <TrueRandom.h> |
004 | #include "SdFat.h" |
005 | SdFat SD; |
006 |
007 | #define LCD_RESET A4 // Can alternately just connect to Arduino's reset pin |
008 | #define LCD_CS A3 // Chip Select goes to Analog 3 |
009 | #define LCD_CD A2 // Command/Data goes to Analog 2 |
010 | #define LCD_WR A1 // LCD Write goes to Analog 1 |
011 | #define LCD_RD A0 // LCD Read goes to Analog 0 |
012 |
013 | #define SD_CS 10 // Card select for shield use |
014 |
015 | Adafruit_TFTLCD tft( LCD_CS, LCD_CD, LCD_WR, LCD_RD, LCD_RESET ); |
016 | uint8_t spi_save; |
017 | File root; |
018 |
019 | void setup () |
020 | { |
021 | Serial .begin(9600); |
022 |
023 | tft.reset(); |
024 | tft.begin( tft.readID() ); |
025 | tft.setRotation(3); |
026 |
027 | Serial .print(F( "Initializing SD card..." )); |
028 | if (!SD.begin( SD_CS )) { |
029 | Serial .println(F( "failed!" )); |
030 | return ; |
031 | } |
032 | Serial .println(F( "OK!" )); |
033 | spi_save = SPCR; |
034 | } |
035 |
036 | void loop () |
037 | { |
038 | String bitmap = (String) TrueRandom.random( 2400 ) + ".bmp" ; |
039 | tft.fillScreen(0); |
040 | bmpDraw( string2char( bitmap ), 0, 0 ); |
041 | delay(5000); |
042 | } |
043 |
044 | char * string2char( String command ) { |
045 | if (command.length() != 0) { |
046 | char *p = const_cast< char *>(command.c_str()); |
047 | return p; |
048 | } |
049 | } |
050 |
051 | // This function opens a Windows Bitmap (BMP) file and |
052 | // displays it at the given coordinates. It's sped up |
053 | // by reading many pixels worth of data at a time |
054 | // (rather than pixel by pixel). Increasing the buffer |
055 | // size takes more of the Arduino's precious RAM but |
056 | // makes loading a little faster. 20 pixels seems a |
057 | // good balance. |
058 |
059 | #define BUFFPIXEL 20 |
060 |
061 | void bmpDraw( char *filename, int x, int y) { |
062 | File bmpFile; |
063 | int bmpWidth, bmpHeight; // W+H in pixels |
064 | uint8_t bmpDepth; // Bit depth (currently must be 24) |
065 | uint32_t bmpImageoffset; // Start of image data in file |
066 | uint32_t rowSize; // Not always = bmpWidth; may have padding |
067 | uint8_t sdbuffer[3 * BUFFPIXEL]; // pixel in buffer (R+G+B per pixel) |
068 | uint16_t lcdbuffer[BUFFPIXEL]; // pixel out buffer (16-bit per pixel) |
069 | uint8_t buffidx = sizeof (sdbuffer); // Current position in sdbuffer |
070 | boolean goodBmp = false ; // Set to true on valid header parse |
071 | boolean flip = true ; // BMP is stored bottom-to-top |
072 | int w, h, row, col; |
073 | uint8_t r, g, b; |
074 | uint32_t pos = 0, startTime = millis(); |
075 | uint8_t lcdidx = 0; |
076 | boolean first = true ; |
077 |
078 | if ((x >= tft.width()) || (y >= tft.height())) return ; |
079 |
080 | Serial .println(); |
081 | Serial .print( F( "Loading image '" ) ); |
082 | Serial .print(filename); |
083 | Serial .println( '\'' ); |
084 | // Open requested file on SD card |
085 | SPCR = spi_save; |
086 | if ((bmpFile = SD.open(filename, O_READ)) == NULL) { |
087 | Serial .print( "File not found" ); |
088 | return ; |
089 | } |
090 |
091 | // Parse BMP header |
092 | if (sdcard_read16(bmpFile) == 0x4D42) { // BMP signature |
093 | Serial .print(F( "File size: " )); Serial .println(sdcard_read32(bmpFile)); |
094 | ( void )sdcard_read32(bmpFile); // Read & ignore creator bytes |
095 | bmpImageoffset = sdcard_read32(bmpFile); // Start of image data |
096 | Serial .print(F( "Image Offset: " )); Serial .println(bmpImageoffset, DEC); |
097 | // Read DIB header |
098 | Serial .print(F( "Header size: " )); Serial .println(sdcard_read32(bmpFile)); |
099 | bmpWidth = sdcard_read32(bmpFile); |
100 | bmpHeight = sdcard_read32(bmpFile); |
101 | if (sdcard_read16(bmpFile) == 1) { // # planes -- must be '1' |
102 | bmpDepth = sdcard_read16(bmpFile); // bits per pixel |
103 | Serial .print(F( "Bit Depth: " )); Serial .println(bmpDepth); |
104 | if ((bmpDepth == 24) && (sdcard_read32(bmpFile) == 0)) { // 0 = uncompressed |
105 |
106 | goodBmp = true ; // Supported BMP format -- proceed! |
107 | Serial .print(F( "Image size: " )); |
108 | Serial .print(bmpWidth); |
109 | Serial .print( 'x' ); |
110 | Serial .println(bmpHeight); |
111 |
112 | // BMP rows are padded (if needed) to 4-byte boundary |
113 | rowSize = (bmpWidth * 3 + 3) & ~3; |
114 |
115 | // If bmpHeight is negative, image is in top-down order. |
116 | // This is not canon but has been observed in the wild. |
117 | if (bmpHeight < 0) { |
118 | bmpHeight = -bmpHeight; |
119 | flip = false ; |
120 | } |
121 |
122 | // Crop area to be loaded |
123 | w = bmpWidth; |
124 | h = bmpHeight; |
125 | if ((x + w - 1) >= tft.width()) w = tft.width() - x; |
126 | if ((y + h - 1) >= tft.height()) h = tft.height() - y; |
127 |
128 | // Set TFT address window to clipped image bounds |
129 | SPCR = 0; |
130 | tft.setAddrWindow(x, y, x + w - 1, y + h - 1); |
131 |
132 | for (row = 0; row < h; row++) { // For each scanline... |
133 | // Seek to start of scan line. It might seem labor- |
134 | // intensive to be doing this on every line, but this |
135 | // method covers a lot of gritty details like cropping |
136 | // and scanline padding. Also, the seek only takes |
137 | // place if the file position actually needs to change |
138 | // (avoids a lot of cluster math in SD library). |
139 | if (flip) // Bitmap is stored bottom-to-top order (normal BMP) |
140 | pos = bmpImageoffset + (bmpHeight - 1 - row) * rowSize; |
141 | else // Bitmap is stored top-to-bottom |
142 | pos = bmpImageoffset + row * rowSize; |
143 | SPCR = spi_save; |
144 | if (bmpFile.position() != pos) { // Need seek? |
145 | bmpFile.seek(pos); |
146 | buffidx = sizeof (sdbuffer); // Force buffer reload |
147 | } |
148 |
149 | for (col = 0; col < w; col++) { // For each column... |
150 | // Time to read more pixel data? |
151 | if (buffidx >= sizeof (sdbuffer)) { // Indeed |
152 | // Push LCD buffer to the display first |
153 | if (lcdidx > 0) { |
154 | SPCR = 0; |
155 | tft.pushColors(lcdbuffer, lcdidx, first); |
156 | lcdidx = 0; |
157 | first = false ; |
158 | } |
159 | SPCR = spi_save; |
160 | bmpFile.read(sdbuffer, sizeof (sdbuffer)); |
161 | buffidx = 0; // Set index to beginning |
162 | } |
163 |
164 | // Convert pixel from BMP to TFT format |
165 | b = sdbuffer[buffidx++]; |
166 | g = sdbuffer[buffidx++]; |
167 | r = sdbuffer[buffidx++]; |
168 | lcdbuffer[lcdidx++] = tft.color565(r, g, b); |
169 | } // end pixel |
170 | } // end scanline |
171 | // Write any remaining data to LCD |
172 | if (lcdidx > 0) { |
173 | SPCR = 0; |
174 | tft.pushColors(lcdbuffer, lcdidx, first); |
175 | } |
176 | Serial .print(F( "Loaded in " )); |
177 | Serial .print(millis() - startTime); |
178 | Serial .println( " ms" ); |
179 | } // end goodBmp |
180 | } |
181 | } |
182 |
183 | bmpFile.close(); |
184 | if (!goodBmp) Serial .println( "BMP format not recognized." ); |
185 | } |
186 |
187 | // sdfat.h fix |
188 | uint16_t sdcard_read16(File &f) |
189 | { |
190 | uint16_t result; |
191 | ((uint8_t *)&result)[0] = f.read(); // LSB |
192 | ((uint8_t *)&result)[1] = f.read(); // MSB |
193 | return result; |
194 | } |
195 |
196 | // sdfat.h fix |
197 | uint32_t sdcard_read32(File &f) |
198 | { |
199 | uint32_t result; |
200 | ((uint8_t *)&result)[0] = f.read(); // LSB |
201 | ((uint8_t *)&result)[1] = f.read(); |
202 | ((uint8_t *)&result)[2] = f.read(); |
203 | ((uint8_t *)&result)[3] = f.read(); // MSB |
204 | return result; |
205 | } |
Adafruit_GFX - помоему там есть контрастности регулировка.. по крайней мере на OLED дисплеях работает. И непонятно низкая гамма/констрастность или низкая яркость подсветки??
дисплей может мерцать при нехватке тока, или плохой контакт земли или vcc
Очень сложно сфотографировать телефоном экран, да ещё и чтобы показать яркость, но я попробовал:
"слабая яркость" - все цвета блеклые, тёмные, картинка плохо просматривается даже вблизи и с включенным светом, с расстояния в пол-метра - метр уже не разобрать, что же там нарисовано:
но после нажатия ресета - (пока сам дисплей и microsd карта неинициализирована?), картинку на дисплее видно ярко, ясно и чётко, так же, как на большом брате, цвета яркие, сочные, видно орлиным глазом метров за несколько:
На глазок этот эффект больше похож на пониженный уровень гамма-коррекции. Диоды подсветки видно с боков экрана, их яркость, вроде как, при моих манипуляциях не изменяется. Питание переключал, пробовал и от usb, и от БП на 9В/1А, и оба вместе - на ситуацию это не повлияло.
UPD: про мерцание при выводе bmp - думаю, что шилд всё же воткнут крепко - потому что оно как бы на самом деле не мерцание, а просто глазом отмечается, как быстрое дрожание эдаких бегущих полосок, видимо глаз таким образом отмечает задержки между чтением буфера с карты и отправкой его на дисплей.
последняя версия библиотеки, попробуйте
https://github.com/prenticedavid/MCUFRIEND_kbv
Пробовал, белый экран, не дружит она с китайским поделием на 4535 :(
Если прервать крутящийся демо скетч от mcufriend заливкой моего, то после ресета на дисплее на миг видно нарисованные демкой прямоугольники, то есть внизу, "под белым экраном" оно всё-таки как-то работает и в память дисплея пересылает байтики правильно.
Мучения продолжаются, пока удалось в инициализации выставить все резисторы для гамма-коррекции в 0 Ом, стало чуть поярче, но все ещё далеко от идеала, который виден из видеопамяти после нажатия ресета.
01
0x30, 0x0000,
02
0x31, 0x0000,
03
0x32, 0x0000,
04
0x35, 0x0000,
05
0x36, 0x0000,
06
0x37, 0x0000,
07
0x38, 0x0000,
08
0x39, 0x0000,
09
0x3C, 0x0000,
10
0x3D, 0x0000,
Мучения продолжаются, пока удалось в инициализации выставить все резисторы для гамма-коррекции в 0 Ом, стало чуть поярче, но все ещё далеко от идеала, который виден из видеопамяти после нажатия ресета.
01
0x30, 0x0000,
02
0x31, 0x0000,
03
0x32, 0x0000,
04
0x35, 0x0000,
05
0x36, 0x0000,
06
0x37, 0x0000,
07
0x38, 0x0000,
08
0x39, 0x0000,
09
0x3C, 0x0000,
10
0x3D, 0x0000,
(1) попробуйте просто закоментить регистры гаммы, пусть будут значения по умолчанию в контроллере после сброса.
Для минимального инита вообще хватает 3-4 команды в нем , (2) попробуйте путем коментирования исключать один регистр за другим, оставить самые необходимые.
01
к примеру для контроллеров у которых
02
setxy
03
LCD_Write_COM(0x2A);
//column
04
LCD_Write_DATA(x1>>8);
05
LCD_Write_DATA(x1);
06
LCD_Write_DATA(x2>>8);
07
LCD_Write_DATA(x2);
08
LCD_Write_COM(0x2B);
//page
09
LCD_Write_DATA(y1>>8);
10
LCD_Write_DATA(y1);
11
LCD_Write_DATA(y2>>8);
12
LCD_Write_DATA(y2);
13
LCD_Write_COM(0x2C);
//write
14
15
16
но самый короткий инит получился:
17
18
19
LCD_Write_COM(0x11);
// обязательно
20
delay(100);
21
22
//LCD_Write_COM(0x13);
23
24
LCD_Write_COM(0x3A);
// Pixel Format Set
25
LCD_Write_DATA(0x05);
//0x05-65k color565
26
27
LCD_Write_COM(0x36);
// Memory Acces Control
28
LCD_Write_DATA(0x48);
//e8-orig , 48-ili9327 16bit! ,
29
30
LCD_Write_COM(0x29);
// обязательно
31
32
LCD_Write_COM(0x2C);
// обязательно
http://arduino.ru/forum/apparatnye-voprosy/arduino-i-displei-ot-sotikov-mobilnykh-telefonov?page=1#comment-175988
Вообще похоже что инит не соответствует контроллеру, (4) попробуйте считать тип контроллера, в примерах адафруита он посылает его в сериал порт,
Есть ещё одно предположение, это изменение уровня питания диспа (5) проверте мультиметром в обоих случаях. Мож использование карты , а она же включена в дешевых шилдах напрямую, логические уровни 5в с ардуины поднимают через нее питалово 3,3в ( т.к. microSD и дисп запитаны от одного стаба 3,3в. ) А от повышенного питалова , внутренние преобразователи на кристалле на стекле, начинают выше кочегарить разновеликие доплнительные напряжения для матрицы, из-за этого и бывает изменение яркости и контраста. Правда подключенная подсветка напрямую к стабу немного нагружает его, но надо бы проветь, мало ли с 3,3в он поднимается до 3,6в или нежелательно ещё выше.
// при полном ините, в регистры изменяются параметры по умолчанию, по подведенному питанию - для 3,3в надо одни значения , для 2,8в - другие, при максимально-критическом 3,6в - третьи.
slider спасибо, программные советы с утра уже успел поперебирать :( . Первым делом (4) считал примером lcd_id_readreg, оттуда получил 0х4535 и все остальные регистры по нулям, в тексте mcufriend нет поддержки этого контроллера. Нашёл даташит на LG4535, (3) инит в используемой библиотеке оказался полностью скопирован из даташита. Комментировал (1) регистры гаммы, пробовал (2) комментировать другие регистры - все безрезультатно, яркость по-прежнему остаётся слабой. Пробовал отправлять ардуину в сон после отрисовки, пробуждался обратно по таймеру - но и во сне яркость та же. Найти минимальный инит вот ещё только не пробовал. Боюсь, как бы не (5) - а при ресете microSD [отваливается/засыпает/ещё что-нибудь] и яркость на секунду становится максимальной.
Вот сдесь посмотрите http://ceezblog.info/2015/04/20/240x320-28-tft-shield-driver-4535-for-ar...
Выдалось ещё немного времени покопаться с этим дисплей шилдом.
Последнюю библиотеку смотрел, да тачскрин-то работает, и инит в этой библиотеке такой же. Вынул microSD, вывел битмап с компа через сериал - яркость всё та же, низкая. Если с выведенной картинкой зажать и держать ресет, тем самым отрубив ардуину - высокая. Нашел на форуме arduino.cc несколько постов, люди пишут про ту же проблему, шилды у них подобные, но на других чипах, так что, по ходу, такой уж мне достался дисплей с али - самому рисовать примитивы ещё приемлемо, а для фоторамки слишком тёмный => видимо, расходимся, всем спасибо за внимание.