TFT LCD для Ардуино
- Войдите на сайт для отправки комментариев
Пт, 22/09/2017 - 01:54
Здравствуйте.
Недавно приобрёл сенсорный 3.95-дюймовый TFT LCD для Arduino Uno R3 (фото ниже) китайской фирмы "mcufriend" (http://www.mcufriend.com).


Установил этот шилд на плату Arduino Uno R3 (см. фото).

Перебрал кучу библиотек, но до сих пор созерцаю белый экран (фото ниже).

Не могу определить модель видеоконтроллера. При считывании ID программой LCD_ID_Reader получаю:

А graphicstest (из библиотеки "Самурай") выдаёт следующую информацию:

Пожалуйста, подскажите:
- Какой микроконтроллер имеет такой ID.
- Какая к нему подходит библиотека.
- Насколько хорош вышеописанный экран (возможно, кто-нибудь им пользовался).
- Можно ли его установить на Arduino Due.
Заранее благодарен всем откликнувшимся.
Дмитрий.
поищите в инете adafruit ili9488 , mcufriend ili9488 .
http://arduino.ru/forum/apparatnye-voprosy/arduino-i-displei-ot-sotikov-mobilnykh-telefonov?page=8#comment-290976
// напишите потом что помогло .
Спасибо, slider!
Вы мне очень сильно помогли. Я и раньше подозревал, что этот экранчик управляется ili9488. Но все библиотеки, которые я для него скачивал, не подходили. В том числе mcufriend ili9488 и adafruit ili9488. Хотя читал на форумах, что они кому-то подошли. Тогда я стал считывать ID. Вначале программы, названия которых указаны выше, выдавали ID = 0x0000. И я уже собирался было указать именно его. Но во время подготовки данной темы решил ещё раз проверить. Заново откомпилировал тексты программ, отсоединил экран от платы Arduino и снова его подсоединил. И...о, чудо (ID уже не 0x0000, а 0x0101)! Но на этом чудеса не закончились...
...Когда вы, slider, посоветовали мне посмотреть библиотеки, которые не подошли, я решил начать с библиотеки mcufriend ili9488. В поисковой строке Googl-а прямо так и набрал: "mcufriend ili9488". И наткнулся вот на эту ссылку: https://ruclip.com/video/VnRVbxQESnY/arduino-ili9488-480x320-tft-lcd-review.html. Перейдя по ней, я нашёл видеоинструкцию по установке и дальнейшей настройке данного экрана. А также ссылки на библиотеки. Вот они:
forum.arduino.cc/index.php?topic=366304.msg2524865#msg2524865.
github.com/adafruit/Adafruit-GFX-Library.
github.com/adafruit/Touch-Screen-Library.
Я скачал их и установил. Затем сделал всё так, как было показано в видео (правда, не пришлось исправлять строку в скетче (Так откомпилировался!)). Да и строка в нём, почему-то, другая! И случилось новое чудо (экран заработал):
На предыдущем фото график y = tg(x) (жёлтая линия) какой-то странный (Линия не сплошная!). Вот скетч:
Это от того, что в скетче что-то напутали или библиотеки "не совсем те, что надо"?
Вот ещё фото работающего экранчика:
И новое чудо...
...Вы только взгляните на фото ниже!
ID-то не тот, что был считан ранее!!! В связи с этим следующий вопрос...
эт хорошо.
прикольная читалка ID, если будет время поизучаю.
id может лежать в разных местах и по разному , id reader-ы заточены не на все места поиска , и как они могут выдать несколько разных мест как одно итоговое? только если им известны тонкости некоторых контроллеров, но далеко не всех.
каков ответ - лог от читалки v5.3 ? http://arduino.ru/forum/apparatnye-voprosy/arduino-i-displei-ot-sotikov-mobilnykh-telefonov?page=8#comment-290976
ID 0x6814 это контроллер RM68140 , он сродни ILI9486 , похож на ILI9488 , поэтому и команды запуска в основном подходят (разница заметна может быть начальных настройках в гамме цветности).
По тангенсу все норм., ведь рисование в скетче не апроксимированной линией, а точками. в синусе плавно и медленно изменение , а в тангенсе скачок это естественно.
..:
Скетч "Touch_shield_kbv":
// the regular Adafruit "TouchScreen.h" library only works on AVRs // different mcufriend shields have Touchscreen on different pins // and rotation. // Run the UTouch_calibr_kbv sketch for calibration of your shield #include <Adafruit_GFX.h> // Core graphics library //#include <Adafruit_TFTLCD.h> // Hardware-specific library //Adafruit_TFTLCD tft(A3, A2, A1, A0, A4); #include <MCUFRIEND_kbv.h> MCUFRIEND_kbv tft; // hard-wired for UNO shields anyway. #include <TouchScreen.h> #if defined(__SAM3X8E__) #undef __FlashStringHelper::F(string_literal) #define F(string_literal) string_literal #endif // These are the pins for some typical shields! // S6D0154: YP=A1, XM=A2, YM=7, XP=6 // ST7783 : YP=A2, XM=A1, YM=6, XP=7 // ILI9320: YP=A2, XM=A3, YM=8, XP=9 // ILI9325: YP=A1, XM=A2, YM=7, XP=6 // ILI9325BG: YP=A2, XM=A1, YM=6, XP=7 // ILI9341: YP=A2, XM=A1, YM=7, XP=6 // ILI9488: YP=A1, XM=A2, YM=7, XP=6 // R65109V: YP=A2, XM=A1, YM=6, XP=7 // most mcufriend shields use these pins and Portrait mode: uint8_t YP = A1; // must be an analog pin, use "An" notation! uint8_t XM = A2; // must be an analog pin, use "An" notation! uint8_t YM = 7; // can be a digital pin uint8_t XP = 6; // can be a digital pin uint8_t SwapXY = 0; uint16_t TS_LEFT = 920; uint16_t TS_RT = 150; uint16_t TS_TOP = 940; uint16_t TS_BOT = 120; char *name = "Unknown controller"; // For better pressure precision, we need to know the resistance // between X+ and X- Use any multimeter to read it // For the one we're using, its 300 ohms across the X plate TouchScreen ts = TouchScreen(XP, YP, XM, YM, 300); TSPoint tp; #define MINPRESSURE 20 #define MAXPRESSURE 1000 #define SWAP(a, b) {uint16_t tmp = a; a = b; b = tmp;} int16_t BOXSIZE; int16_t PENRADIUS = 3; uint16_t identifier, oldcolor, currentcolor; uint8_t Orientation = 0; //PORTRAIT // Assign human-readable names to some common 16-bit color values: #define BLACK 0x0000 #define BLUE 0x001F #define RED 0xF800 #define GREEN 0x07E0 #define CYAN 0x07FF #define MAGENTA 0xF81F #define YELLOW 0xFFE0 #define WHITE 0xFFFF void show_Serial(void) { Serial.print(F("Found ")); Serial.print(name); Serial.println(F(" LCD driver")); Serial.print(F("ID=0x")); Serial.println(identifier, HEX); Serial.println("Screen is " + String(tft.width()) + "x" + String(tft.height())); Serial.println("Calibration is: "); Serial.println("LEFT = " + String(TS_LEFT) + " RT = " + String(TS_RT)); Serial.println("TOP = " + String(TS_TOP) + " BOT = " + String(TS_BOT)); Serial.print("Wiring is: "); Serial.println(SwapXY ? "SWAPXY" : "PORTRAIT"); Serial.println("YP=" + String(YP) + " XM=" + String(XM)); Serial.println("YM=" + String(YM) + " XP=" + String(XP)); } void show_tft(void) { tft.setCursor(0, 0); tft.setTextSize(2); tft.print(F("Found ")); tft.print(name); tft.println(F(" LCD")); tft.setTextSize(1); tft.print(F("ID=0x")); tft.println(identifier, HEX); tft.println("Screen is " + String(tft.width()) + "x" + String(tft.height())); tft.println("Calibration is: "); tft.println("LEFT = " + String(TS_LEFT) + " RT = " + String(TS_RT)); tft.println("TOP = " + String(TS_TOP) + " BOT = " + String(TS_BOT)); tft.print("\nWiring is: "); if (SwapXY) { tft.setTextColor(CYAN); tft.setTextSize(2); } tft.println(SwapXY ? "SWAPXY" : "PORTRAIT"); tft.println("YP=" + String(YP) + " XM=" + String(XM)); tft.println("YM=" + String(YM) + " XP=" + String(XP)); tft.setTextSize(2); tft.setTextColor(RED); tft.setCursor((tft.width() - 48) / 2, (tft.height() * 2) / 4); tft.print("EXIT"); tft.setTextColor(YELLOW, BLACK); tft.setCursor(0, (tft.height() * 6) / 8); tft.print("Touch screen for loc"); while (1) { tp = ts.getPoint(); pinMode(XM, OUTPUT); pinMode(YP, OUTPUT); pinMode(XP, OUTPUT); pinMode(YM, OUTPUT); if (tp.z < MINPRESSURE || tp.z > MAXPRESSURE) continue; if (tp.x > 450 && tp.x < 570 && tp.y > 450 && tp.y < 570) break; tft.setCursor(0, (tft.height() * 3) / 4); tft.print("tp.x=" + String(tp.x) + " tp.y=" + String(tp.y) + " "); } } void setup(void) { uint16_t tmp; tft.begin(9600); tft.reset(); identifier = tft.readID(); // if (identifier == 0) identifier = 0x9341; if (0) { } else if (identifier == 0x0154) { name = "S6D0154"; TS_LEFT = 914; TS_RT = 181; TS_TOP = 957; TS_BOT = 208; } else if (identifier == 0x7783) { name = "ST7781"; TS_LEFT = 865; TS_RT = 155; TS_TOP = 942; TS_BOT = 153; SwapXY = 1; } else if (identifier == 0x7789) { name = "ST7789V"; YP = A2; XM = A1; YM = 7; XP = 6; TS_LEFT = 906; TS_RT = 169; TS_TOP = 161; TS_BOT = 919; } else if (identifier == 0x9320) { name = "ILI9320"; YP = A3; XM = A2; YM = 9; XP = 8; TS_LEFT = 902; TS_RT = 137; TS_TOP = 941; TS_BOT = 134; } else if (identifier == 0x9325) { name = "ILI9325"; TS_LEFT = 900; TS_RT = 103; TS_TOP = 96; TS_BOT = 904; } else if (identifier == 0x9325) { name = "ILI9325 Green Dog"; TS_LEFT = 900; TS_RT = 130; TS_TOP = 940; TS_BOT = 130; } else if (identifier == 0x9327) { name = "ILI9327"; TS_LEFT = 899; TS_RT = 135; TS_TOP = 935; TS_BOT = 79; SwapXY = 1; } else if (identifier == 0x9329) { name = "ILI9329"; TS_LEFT = 143; TS_RT = 885; TS_TOP = 941; TS_BOT = 131; SwapXY = 1; } else if (identifier == 0x9341) { name = "ILI9341 BLUE"; TS_LEFT = 920; TS_RT = 139; TS_TOP = 944; TS_BOT = 150; SwapXY = 0; } else if (identifier == 0) { name = "ILI9341 DealExtreme"; TS_LEFT = 893; TS_RT = 145; TS_TOP = 930; TS_BOT = 135; SwapXY = 1; } else if (identifier == 0 || identifier == 0x9341) { name = "ILI9341"; TS_LEFT = 128; TS_RT = 911; TS_TOP = 105; TS_BOT = 908; SwapXY = 1; } else if (identifier == 0x9486) { name = "ILI9486"; TS_LEFT = 904; TS_RT = 170; TS_TOP = 950; TS_BOT = 158; } else if (identifier == 0x9488) { name = "ILI9488"; TS_LEFT = 904; TS_RT = 170; TS_TOP = 950; TS_BOT = 158; } else if (identifier == 0xB509) { name = "R61509V"; TS_LEFT = 889; TS_RT = 149; TS_TOP = 106; TS_BOT = 975; SwapXY = 1; } else { name = "unknown"; } switch (Orientation) { // adjust for different aspects case 0: break; //no change, calibrated for PORTRAIT case 1: tmp = TS_LEFT, TS_LEFT = TS_BOT, TS_BOT = TS_RT, TS_RT = TS_TOP, TS_TOP = tmp; break; case 2: SWAP(TS_LEFT, TS_RT); SWAP(TS_TOP, TS_BOT); break; case 3: tmp = TS_LEFT, TS_LEFT = TS_TOP, TS_TOP = TS_RT, TS_RT = TS_BOT, TS_BOT = tmp; break; } Serial.begin(9600); ts = TouchScreen(XP, YP, XM, YM, 300); //call the constructor AGAIN with new values. tft.begin(identifier); show_Serial(); tft.setRotation(Orientation); tft.fillScreen(BLACK); show_tft(); BOXSIZE = tft.width() / 6; tft.fillScreen(BLACK); tft.fillRect(0, 0, BOXSIZE, BOXSIZE, RED); tft.fillRect(BOXSIZE, 0, BOXSIZE, BOXSIZE, YELLOW); tft.fillRect(BOXSIZE * 2, 0, BOXSIZE, BOXSIZE, GREEN); tft.fillRect(BOXSIZE * 3, 0, BOXSIZE, BOXSIZE, CYAN); tft.fillRect(BOXSIZE * 4, 0, BOXSIZE, BOXSIZE, BLUE); tft.fillRect(BOXSIZE * 5, 0, BOXSIZE, BOXSIZE, MAGENTA); tft.drawRect(0, 0, BOXSIZE, BOXSIZE, WHITE); currentcolor = RED; delay(1000); } void loop() { uint16_t xpos, ypos; //screen coordinates tp = ts.getPoint(); //tp.x, tp.y are ADC values // if sharing pins, you'll need to fix the directions of the touchscreen pins pinMode(XM, OUTPUT); pinMode(YP, OUTPUT); pinMode(XP, OUTPUT); pinMode(YM, OUTPUT); // digitalWrite(XM, HIGH); // digitalWrite(YP, HIGH); // we have some minimum pressure we consider 'valid' // pressure of 0 means no pressing! if (tp.z > MINPRESSURE && tp.z < MAXPRESSURE) { // is controller wired for Landscape ? or are we oriented in Landscape? if (SwapXY != (Orientation & 1)) SWAP(tp.x, tp.y); // scale from 0->1023 to tft.width i.e. left = 0, rt = width // most mcufriend have touch (with icons) that extends below the TFT // screens without icons need to reserve a space for "erase" // scale the ADC values from ts.getPoint() to screen values e.g. 0-239 xpos = map(tp.x, TS_LEFT, TS_RT, 0, tft.width()); ypos = map(tp.y, TS_TOP, TS_BOT, 0, tft.height()); // are we in top color box area ? if (ypos < BOXSIZE) { //draw white border on selected color box oldcolor = currentcolor; if (xpos < BOXSIZE) { currentcolor = RED; tft.drawRect(0, 0, BOXSIZE, BOXSIZE, WHITE); } else if (xpos < BOXSIZE * 2) { currentcolor = YELLOW; tft.drawRect(BOXSIZE, 0, BOXSIZE, BOXSIZE, WHITE); } else if (xpos < BOXSIZE * 3) { currentcolor = GREEN; tft.drawRect(BOXSIZE * 2, 0, BOXSIZE, BOXSIZE, WHITE); } else if (xpos < BOXSIZE * 4) { currentcolor = CYAN; tft.drawRect(BOXSIZE * 3, 0, BOXSIZE, BOXSIZE, WHITE); } else if (xpos < BOXSIZE * 5) { currentcolor = BLUE; tft.drawRect(BOXSIZE * 4, 0, BOXSIZE, BOXSIZE, WHITE); } else if (xpos < BOXSIZE * 6) { currentcolor = MAGENTA; tft.drawRect(BOXSIZE * 5, 0, BOXSIZE, BOXSIZE, WHITE); } if (oldcolor != currentcolor) { //rub out the previous white border if (oldcolor == RED) tft.fillRect(0, 0, BOXSIZE, BOXSIZE, RED); if (oldcolor == YELLOW) tft.fillRect(BOXSIZE, 0, BOXSIZE, BOXSIZE, YELLOW); if (oldcolor == GREEN) tft.fillRect(BOXSIZE * 2, 0, BOXSIZE, BOXSIZE, GREEN); if (oldcolor == CYAN) tft.fillRect(BOXSIZE * 3, 0, BOXSIZE, BOXSIZE, CYAN); if (oldcolor == BLUE) tft.fillRect(BOXSIZE * 4, 0, BOXSIZE, BOXSIZE, BLUE); if (oldcolor == MAGENTA) tft.fillRect(BOXSIZE * 5, 0, BOXSIZE, BOXSIZE, MAGENTA); } } // are we in drawing area ? if (((ypos - PENRADIUS) > BOXSIZE) && ((ypos + PENRADIUS) < tft.height())) { tft.fillCircle(xpos, ypos, PENRADIUS, currentcolor); } // are we in erase area ? if (ypos > tft.height() - 10) { // press the bottom of the screen to erase tft.fillRect(0, BOXSIZE, tft.width(), tft.height() - BOXSIZE, BLACK); } } }Вот снова LCD_ID_Reader (равно как и LCD_ID_readreg из пакета "MCUFRIEND_kbv-2.9.3") выдаёт: "ID = 0x0000".
Пожалуйста, не сочтите этот вопрос глупым. У меня большой опыт написания программ для компьютеров, но программированием микроконтроллеров и робототехникой я занялся совсем недавно. И просто хочу во всём разобраться.
Цитата:
Простите, не понял от какой именно читалки.
Извините, глупость написал (невнимательно посмотрел - не заметил ссылки) :)
Сейчас посмотрю.
1. возможно дело в алгоритме
170}elseif(identifier == 0) {171name ="ILI9341 DealExtreme";172TS_LEFT = 893; TS_RT = 145; TS_TOP = 930; TS_BOT = 135;173SwapXY = 1;174}elseif(identifier == 0 || identifier == 0x9341) {175name ="ILI9341";176TS_LEFT = 128; TS_RT = 911; TS_TOP = 105; TS_BOT = 908;177SwapXY = 1;выдается значение из последне считанного регистра D3h , а почему экран запоказывал , так это от инита ILI9341 , он тоже схож.
в других читалках по другому.
сверить какой именно контроллер сможет показать читалка v5.3 , просто запустить и заглянуть в монитор порта.
2. лучше указывать ili9486 (у ,библиотеки UTFT тож есть его поддержка, но именно с таким шилдом надо использовать пиленную либу под ili9327 и в ней заменить инит на ili9486)
в KVB и Adafruit ,думаю можно без болезненно использовать инит от ili9488 если нет ILI9486 , включив его принудительно. Для этого в скетче , вместо identifier = tft.readID(); написать identifier = 0x9486; можно еще попробовать identifier = 0x9488;
Вот:
не скриншот, а весь лог, прочтите внимательней, там написал как приложить.
Хорошо прочту.
Забыл сказать, что читалка v5.3 даёт не только ответ-лог, но и выводит на экран дисплейчика различные изображения. Например, вот такие:
2. лучше указывать ili9486 (у ,библиотеки UTFT тож есть его поддержка, но именно с таким шилдом надо использовать пиленную либу под ili9327 и в ней заменить инит на ili9486)
в KVB и Adafruit ,думаю можно без болезненно использовать инит от ili9488 если нет ILI9486 , включив его принудительно. Для этого в скетче , вместо identifier = tft.readID(); написать identifier = 0x9486; можно еще попробовать identifier = 0x9488;
Проведя прямую инициализацию получил следующие результаты:
При "identifier = 0x9486":
При "identifier = 0x9488":
При "identifier = 0x6814":
К тому же заметил (уже вечером), что при такой инициализации, как на фотографии выше, изображения на экране имеют более насыщенные цвета (возможно, на нижеприведённом фото это не так заметно), да и выводятся они на экран быстрее:
А использовав подобную инициализацию в скетче
убедился в том, что и калибровка в этом случае происходит точнее:
LEFT 912 RT 160 -2.35
TOP 935 BOT 150 -1.64
Из выше сказанного, на мой взгляд, можно сделать вывод, что при инициализации правильнее использовать 0x6814.
LEFT 912 RT 160 -2.35
TOP 935 BOT 150 -1.64
slider, подскажите, пожалуйста, что это за числа такие отрицательные (-2.35 и -1.64) и как их использовать в скетчах.
Наблюдаю следующее явление:
Загружаю в микроконтроллер платы Arduino Uno R3 скетч "GLUE_Demo_480x320". Вижу на экранчике эту картинку
а затем и другие. Вынимаю кабель USB из соответствующего разъёма компьютера. Снова вставляю. Вначале вижу белый экран. Затем вот этот мусор:
И снова эту картинку:
Подскажите, пожалуйста, как мне избавиться от мусора. Очень не хочется, чтобы что-то подобное появлялось на экране при включении прибора, который я в данный момент создаю.
прикольная читалка ID, если будет время поизучаю.
Возможно, вы уже обнаружили, что это не просто читалка, а своего рода гибрид читалки ID и графического редактора. При запуске этого гибрида вначале появляется вот это:
А после клика по экрану примитивный графический редактор:
Приношу свои извинения за последнюю фотографию (Как я только ни фотографировал, но камера мобильника всё же исказила цвета).
"цветной мусор" это нормально, хорошо - значит дисплей исправен
просто показывает что прежде сохранилось в видеопамяти контроллера. если питания долго небыло , будет просто цветной мусор.
а что его оказалось "долго" видно - это может быть такой недо инит в библиотеке, и реализация (после инита нужна очистка).
в ините , команды очистки (если они есть для этого типа контроллера) и включения (0x29) дисплея должны стоять в самом конце. в начале инита должно выключения (0x28).
Чтоб не забивать голову, можете сразу после инита , сделать очистку экрана командой из библиотеки. возможно задержка показа цветного мусора незначительно уменьшится.
// вот здесь боролись с подобным https://habrahabr.ru/post/278967/
//// в читалке зайдите в Adafruit_TFTLCD.cpp
найдите
про выкладывание лога в третий раз уже не буду напоминать, ...
каков ответ - лог от читалки v5.3 ?
Ответ-лог от читалки v5.3:
Текст в красной рамке на выше приведённом фото встречается и в некоторых других местах лога (в строках № 201, 282, 301, 368, 387).
slider, ещё раз спасибо за помощь в данном вопросе.
Теперь буду изучать библиотеку "MCUFRIEND_kbv-2.9.3".
Если у меня появится новая информация по экранчику или выше указанной библиотеке, обязательно её здесь размещу.
Прошу прощения за чайниковский вопрос, но впервые включаю Ардуино, с целями по теме ветки. Плата - китайская UNO R3, как на фото в старте ветки. Понадобилось погонять неизвестные LCD на предмет определения контроллера. Вопрос: можно ли эту плату переключить на 3.3В, чтобы состыковать с LCD? Как корифеи подключают? Заранее спасибо.
Ответ: переключить эту плату на 3.3V невозможно. Для ее "стыковки" с периферией, имеющей логические сигналы иного уровня, необходимо применить согласователь.
Спасибо за ответ. Да, засада, не ожидал. Вроде и стабилизатор 3.3V есть, казалось бы - просто поставь джамперы переключения питания, как, например, на STM-овских дискавери...
PS. Попробовал таки перевести UNO на 3.3V с возможностью переключения 5 - 3.3. Вроде и получилось просто - одна перерезанная дорожка и две перемычки (если просто на 3.3V). И все работает, скетчи грузятся, UART в терминал долбит, программа отрабатывает, сигналы 3.3V. Но оказалось, что стабилизатор 3.3В вообще не тянет заявленые 50 мА. Сразу просел до 3V, а при подключении LCD (даже без подсветки) - просел еще до сбоев работы. В общем, можно, конечно, еще прилепить стабилизатор помощнее, типа 1117, но это уже такие городухи, что теряется смысл.
Можете взять Pro Mini рассчитанную на 3.3V, если хотите ATMega328 и дисплей с такими уровнями срастить.
Спасибо, у меня, кажется, где-то даже валялась эта Pro Mini, в запас, как говорится. А насчет стабилизатора в UNO - виноват, прогнал, все он держит, но пришлось увеличить конденсатор на выходе. Сейчас пробую с LCD, пока помолчу, а то опять, не подумав, фигню ляпну. :)
Уважаемые ардуинщики! Подскажите пожалуйста, возможно ли собрать метеостанцию на дисплее 3, 95" TFT LCD и UNO. А то я чувствую взялся за непосильное... Очень слабо знакомы TFT
Уважаемые ардуинщики! Подскажите пожалуйста, возможно ли собрать метеостанцию на дисплее 3, 95" TFT LCD и UNO. А то я чувствую взялся за непосильное... Очень слабо знакомы TFT
Возможно. Но FPS на экране будет не ахти.
Возможно или невозможно - прежде всего будет зависеть от интерфейса LCD. Если RGB (а 4 дюйма вполне может быть с RGB) - то врядли. А если MCU - то, думаю, вполне. Если я правильно представляю метеостанцию, то обновлять экран можно нечасто. Т.е. о каком-то FPS речь можно и не вести. :) В общем, нужны конкретные данные дисплея.
Уважаемые ардуинщики! Подскажите пожалуйста, возможно ли собрать метеостанцию на дисплее 3, 95" TFT LCD и UNO. А то я чувствую взялся за непосильное... Очень слабо знакомы TFT
Невозможно: ни одна из этих деталей (TFT LCD и UNO) не может служить датчиком ни одного из метеопараметров (температуры, давления, направления и скорости ветра).
Ну не настолько я туп. Датчики тоже есть. Дисплей для вывода информации.
У меня такой же дисплей о котором идёт речь на форуме. 3,95'' TFT LCD для Arduino UNO. Мне чисто тупо надо понять как их подключить и получить картинку. Использование сенсора не планируется, поэтому аналоговые выходы высвобождаются для датчиков.
AnderSan, не очень понятно, что именно у Вас не получается. Если у Вас такой же дисплей, как обсуждается здесь, то выше достаточно подробно все описано, со ссылками и прочим. Вы это пробовали? Каков результат?
Ну во-первых, это мой первый опыт работы Ардуино, дисплей выбрал потому что размер приемлемый. И только сейчас понял, что дисплей не в ходу. Поэтому первая задача понять как подключить его к Ардуино, вторая разделить дисплей на несколько полей для вывода информации, ну и затем уже понять сколько входов для подключения датчиков.
AnderSan, по порядку. :)
1. Подключение. Поскольку, как я понял, у Вас готовый шилд под UNO, все вопросы подключения уже решены. Просто вставьте.
2. Поскольку, если верить написанному выше, с контроллером и библиотеками все ясно, вопросы инициализации и управления LCD тоже решены, просто используете готовую библиотеку.
3. Первые два пункта - это 80% черновой работы, которая уже решена за Вас. Остается прикладная задача, "разделить на несколько полей" и т.д. Это уже за Вас никто не сделает, Вам нужно разбираться с библиотекой, как залить прямоугольник, как вывести текст и т.д. и реализовать с помощью этого свой интерфейс.
4. Пишу в той последовательности, как у Вас, хотя, как по мне, этот пункт должен быть первым. Какие ноги есть у Ардуино и какие использует шилд видно, если на них посмотреть, там все написано. Это, как правило, 8 бит шины данных и 5 управляющих сигналов. Обычно шилды MCUFRIEND используют:
У меня такой же дисплей о котором идёт речь на форуме. 3,95'' TFT LCD для Arduino UNO. Мне чисто тупо надо понять как их подключить и получить картинку. Использование сенсора не планируется, поэтому аналоговые выходы высвобождаются для датчиков.
Вы уверены, что что-то высвобождается?
Насколько мне известно, одни и те же пины используются поочередно то для ввода, то для вывода.
Поэтому я и обратился на форум. Хотелось собрать метеостанция, что бы была читабильна. Предложенные проекты в инете не устраивают размерами.
А форум тут при чем?
Чего Вы от форума то хотите?
Возникла необходимость (ну так случается иногда) вывести изображение с SD карты. Для этой библиотеки ничего не нашёл готового. Нашёл для UTFT, и немного передрал. Может кому надо #вывод изображения с SD карты на экран с контроллером ili9488 и библиотекой MCUFRIEND_ili9488.
Добавляем в файл MCUFRIEND_kbv.h прототип функции:
В файл MCUFRIEND_kbv.cpp включаем библиотеку SdFat-master (которая тоже должна быть)
Ну и собственно саму функцию:
//******************************* вывод изображения из карты памяти в .raw ******************* void MCUFRIEND_kbv::load(int x, int y, int sx, int sy, char *filename) { uint8_t buf[sx*2]; uint16_t result; if (dataFile.open(filename)) { result=sx; setAddrWindow(x, y, x+sx-1 , y+sy-1); CS_ACTIVE; WriteCmd(_MW); for(int n=0;n<sy;n++) { result=dataFile.read(&buf,sx*2); for (int i=0; i<result; i+=2) { CD_DATA; write8(buf[i]); write8(buf[i+1]); } } } dataFile.close(); CS_IDLE; } //*******************************************************************************************Вызов функции будет выглядить так:
А результат примерно так:
В скетч само собой добавим:
Ну и так далее.
Конвертировать в ".raw" рекомендую программкой ImageConverter565.exe, которая имеется в папке Tools библиотеки UTFT. Ссылок не даю, извините, всё легко найти.
Исходные фото рекомендую открывать в формате .bmp т.к. на выходе более качественный .raw.
Недостаток в том, что функция для вывода объявляет(хоть и локально) массив размером в два раза больше ширины картинки, а это накладывает ограничение на размер изображения по ширине. ( В моём примере это, пожалуй, предел, дальше просто на атм32 заканчивается оперативка). Было желание избавится от буфера, но пока нет времени, да и большой надобности.
Удачи.
Недостаток в том, что функция для вывода объявляет(хоть и локально) массив размером в два раза больше ширины картинки, а это накладывает ограничение на размер изображения по ширине. ( В моём примере это, пожалуй, предел, дальше просто на атм32 заканчивается оперативка). Было желание избавится от буфера, но пока нет времени, да и большой надобности.
Недостаток вызван исключительно тем, что в функции используется буфер, который, по сути, не нужен. Никто не мешает читать хоть побайтно прямо во внутреннем цикле вывода на экран. Естественно, при побайтном чтении скорость работы будет пониже. Но тут уж либо-либо: либо оптимизация по скорости либо по памяти.
for(int n=0;n<sy;n++) { for (int i=0; i<sx; i++) { CD_DATA; write8(dataFile.read()); write8(dataFile.read()); } }Да, согласен, поэтому и не стал от него избавляться.
Ну тогда разумно выбирать размер буфера, исходя из возможностей Ардуины, а не из параметров картинки.
Буфер сжирает память вплоть до отказа работы. Избавиться от него не получается. Даже уменьшить вдвоее размер до ширины изображения не получается. Так то изначальны вариант единственный рабочий (условно).
Это для справки.
Буфер сжирает память вплоть до отказа работы. Избавиться от него не получается.
А, собвственно, почему?
Даже уменьшить вдвоее размер до ширины изображения не получается. Так то изначальны вариант единственный рабочий (условно).
Это для справки.
Вообще-то "по ширине изображения" - это в байтах как раз вдвое больше, чем в пикселях. По причине того, что на 1 пиксель приходится 2 байта.
И размер буфера не критичен. От слова "совсем". С точки зрения функционирования. Но, естественно, влияет на скорость. И именно поэтому вполне возможно, что окажется целесообразным делать буфер не зависящим от ширины изображения, подобрав его размер из условия баланса расходуемой памяти и скорости работы.
Вообще-то "по ширине изображения" - это в байтах как раз вдвое больше, чем в пикселях. По причине того, что на 1 пиксель приходится 2 байта.
Да это как раз и понятно. Вдвое меньше буфер имелось введу выводить изображение из двух частей(по ширине), ну и как вариант, слишком широкого, например шире половины экрана.
И размер буфера не критичен. От слова "совсем". С точки зрения функционирования. Но, естественно, влияет на скорость. И именно поэтому вполне возможно, что окажется целесообразным делать буфер не зависящим от ширины изображения, подобрав его размер из условия баланса расходуемой памяти и скорости работы.
Дело, видимо, в самой функции инициализвции буфера. Я её еле нашёл. Реализацию имею ввиду.
Вобщем если в крации, по половнике выводить изображение, его перекашивает, а если по пикселям, вобще ....
Короче, как уже сказал, нет времени да и необходимости. Может как то потом займусть. А это значит если не припрёт, то никогда.
э.... зачем буфер ? или речь о совсем маленьких картинках?
чем это не годится:
передача уже подготовленного формата байтов для диспа записанного на microsd:
байт с SPI microSD -> байт в дисплей , без забивания всей оперативки буфером и трата тактов процессора, не Jpeg же раскодировать.
современные носители инф. имеют очень быстрый SPI , чем бы их не использовать ? хотя для относительно медленной это не принципиально.
Да это на каждом углу написано. А толку? Все говорят что вывести легко и никто толком не пишет как именно.
Я привел реализацию конкретно для этой библиотеки. С небольшой инструкцией ИМХО. Может кому поможет.
Есть конкретный примеры!? Всюда. Нет? Теорию мы знаем.
Знали бы теорию, не было бы проблем с практикой. А раз проблемы есть, значит, теорию не усвоили.
Кстати, код был в сообщении №37.
Кстати, код был в сообщении №37.
Жаль не оставил скрин от кода из сообщения №37.
Железо заряжено. На слово верьте - не работает.
А что пишет то? Почему не работает?
Так с буфером:
Так, по предложенному алгоритму:
Вот ещё вариант вместо:
читаем так:
Интересно. Чёреый цвет нормально читает, а остальные искажает сильно.
Прям "цвет настроения СИНИЙ"
Ну то есть dataFile.read(), оказывается, возвращает не 8-, а 16-разрядное число.
А по поводу цвета: для отладки выбран очень неудачный рисунок. Гораздо лучше было начать с цветных полос и клиньев.
И, кстати, какова вообще используемая глубина цвета?