Os shields TFT são ecrãs de LCD táteis para a exibição de imagens e a criação de interfaces de usuário, com grafismos mais ou menos complexos, para operar microcontroladores Arduino. Neste tutorial, usamos o shield Kuman TFT 3.5″ (muito próximo do shield 2.8″), mas ele pode ser aplicado para outros shields ou módulos LCD. Basta verificar os pinos utilizados e a compatibilidade da biblioteca.
Material
- Computador
- Arduino UNO ou Mega
- Cabo USB A Macho/B Macho
- Shield LCD TFT
- Cartão SD (opcional)
Princípio de funcionamento
O shield TFT éequipado com um ecrã LCD sensível ao toque que permite exibir imagens a cores e criar interfaces com curvas e botões para interagir e visualizar dados do Arduino. Ele também é equipado com um leitor de cartões micro SD, que pode servir para guardar imagens ou outros dados.
Esquema
O shield TFT é colocado diretamente sobre uma placa Arduino UNO ou Mega. O shield utiliza quase todos os pinos do Arduino UNO. Certifique-se de não usar os mesmos pinos para outros módulos,
Para informação, os pinos disponíveis são:
- pino analógico A5
- pino digital 0
- pino digital 1
Se a funcionalidade tátil do ecrã não for ser utilizada, também é possível usar os pinos A1, A2, 6 e 7.
Se estiver usando um módulo shield ou LCD diferente, verifique bem os pinos a serem utilizados (pinagem).
Calibrar o TouchScreen
Nenhum ecrâ é igual a outro, e para poder utilizá-los corretamente, é preciso obter os valores corretos das dimensões para adaptar a exibição e a detecção da pressão. Para isso, carregamos o código TouchScreen_Calibr_native.ino, presente nos exemplos da biblioteca MCUFRIEND_kbv.h.
Uma vez carregado o código, usamos uma caneta para pressionar, segurar e soltar em vários pontos do ecrã e assim calibrá-lo. Depois disso, as configurações serão exibidas no monitor serial e no ecrã.
Aqui estão os resultados para o Shiel LCD TFT 3.5″
//3.5 Calibration
const int XP = 8, XM = A2, YP = A3, YM = 9; //320x480 ID=0x9486
const int TS_LEFT = 144, TS_RT = 887, TS_TOP = 936, TS_BOT = 87;
E para o Shield LCD TFT 2.8″
//2.8 Calibration
const int XP=8,XM=A2,YP=A3,YM=9; //240x320 ID=0x9341
const int TS_LEFT=907,TS_RT=120,TS_TOP=74,TS_BOT=913;
Código
Para utilizar o objeto TftScreen, usamos as bibliotecas SD.h, Adafruit_GFX.h, MCUFRIEND_kbv.h, e TouchScreen.h, que permitem gerir a comunicação com o cartão SD, a criação de grafismos, o controle do ecrã e o toque. Este exemplo mostra como é fácil utilizar o ecrã (lembre-se de adaptá-lo ao seu equipamento).
//Libraries #include <SD.h>//https://www.arduino.cc/en/reference/SD #include <Adafruit_GFX.h>//https://github.com/adafruit/Adafruit-GFX-Library #include <MCUFRIEND_kbv.h>//https://github.com/prenticedavid/MCUFRIEND_kbv #include <TouchScreen.h> //https://github.com/adafruit/Adafruit_TouchScreen //Constants #define SD_CS 10 #define BLACK 0 #define GREY 21845 #define BLUE 31 #define RED 63488 #define GREEN 2016 #define DARKGREEN 1472 #define CYAN 2047 #define MAGENTA 63519 #define YELLOW 65504 #define GOLD 56768 #define WHITE 65535 //Touch screen configuration #define MINPRESSURE 200 #define MAXPRESSURE 1000 // ALL Touch panels and wiring is DIFFERENT // copy-paste results from TouchScreen_Calibr_native.ino //3.5 Parameters const int XP = 8, XM = A2, YP = A3, YM = 9; //320x480 ID=0x9486 const int TS_LEFT = 144, TS_RT = 887, TS_TOP = 936, TS_BOT = 87; //2.8 Parameters //const int XP = 8, XM = A2, YP = A3, YM = 9; //240x320 ID=0x9341 //const int TS_LEFT = 907, TS_RT = 120, TS_TOP = 74, TS_BOT = 913; TouchScreen ts = TouchScreen(XP, YP, XM, YM, 300); TSPoint p; bool down; int pixel_x, pixel_y; //Touch_getXY() updates global vars //Variables int currentPage = 0, oldPage = -1; //Objects MCUFRIEND_kbv tft; // Button calibration Adafruit_GFX_Button page1_btn, page2_btn; int margin = 5; int btnWidth = 100; int btnHeight = 40; int btnY = 200; void setup() { //Init Serial USB Serial.begin(9600); Serial.println(F("Initialize System")); //Init tft screen uint16_t ID = tft.readID(); if (ID == 0xD3D3) ID = 0x9486; //for 3.5" TFT LCD Shield , 0x9341 for 2.8" TFT LCD Shield tft.begin(ID); tft.setRotation(1);//0-PORTRAIT 1-PAYSAGE 2-REVERSE PORTRAIT 3-REVERSE PAYSAGE //Uncomment if you are using SD /*if (!SD.begin(SD_CS)) { Serial.println(F("initialization failed!")); return; }*/ currentPage = 0; // Indicates that we are at Home Screen } void loop() { down = Touch_getXY(); switch (currentPage) { case 0: if (currentPage != oldPage) { Serial.println(F("Page 1")); drawPage1(); } page2_btn.press(down && page2_btn.contains(pixel_x, pixel_y)); //if (page2_btn.justReleased()) page2_btn.drawButton(); if (page2_btn.justPressed()) { currentPage = 1; } break; case 1: if (currentPage != oldPage) { Serial.println(F("Page 2")); drawPage2(); } page1_btn.press(down && page1_btn.contains(pixel_x, pixel_y)); //if (page1_btn.justReleased()) page1_btn.drawButton(); if (page1_btn.justPressed()) { currentPage = 0; } break; } } void drawPage1() { /* function drawHomePage */ tft.setRotation(1); tft.fillScreen(BLACK); //Title tft.setCursor(0, 10); tft.setTextSize(3); tft.setTextColor(WHITE, BLACK); tft.print("This is page 1"); // Prints the string on the screen tft.drawLine(0, 32, 319, 32, DARKGREEN); // Draws the red line //text tft.setTextSize(3); tft.setTextColor(RED, BLACK); tft.setCursor(tft.width() / 2. - 14 * 3 * 3, 80); tft.print(" Go to page 2 "); //Button page2_btn.initButton(&tft, tft.width() / 2., 200, 2 * btnWidth, btnHeight, WHITE, GREEN, BLACK, "Page 2", 2); page2_btn.drawButton(false); oldPage = currentPage; } void drawPage2() { /* function drawHomePage */ tft.setRotation(1); tft.fillScreen(GREY); //Title tft.setCursor(0, 10); tft.setTextSize(3); tft.setTextColor(WHITE, GREY); tft.print("This is page 2"); // Prints the string on the screen tft.drawLine(0, 32, 319, 32, DARKGREEN); // Draws the red line //text tft.setTextSize(3); tft.setTextColor(GREEN, BLACK); tft.setCursor(tft.width() / 2. - 14 * 3 * 3, 80); tft.print(" Go to page 1 "); //Button page1_btn.initButton(&tft, tft.width() / 2., 200, 2 * btnWidth, btnHeight, WHITE, RED, BLACK, "Page 1", 2); page1_btn.drawButton(false); oldPage = currentPage; } /************************************************************************************ UTILITY FUNCTION *************************************************************************************/ bool Touch_getXY(void) { p = ts.getPoint(); pinMode(YP, OUTPUT); //restore shared pins pinMode(XM, OUTPUT); digitalWrite(YP, HIGH); digitalWrite(XM, HIGH); bool pressed = (p.z > MINPRESSURE && p.z < MAXPRESSURE); if (pressed) { if (tft.width() <= tft.height()) { //Portrait pixel_x = map(p.x, TS_LEFT, TS_RT, 0, tft.width()); //.kbv makes sense to me pixel_y = map(p.y, TS_TOP, TS_BOT, 0, tft.height()); } else { pixel_x = map(p.y, TS_TOP, TS_BOT, 0, tft.width()); pixel_y = map(p.x, TS_RT, TS_LEFT, 0, tft.height()); } } return pressed; }
Bônus: Exemplo de interface gráfica
Neste exemplo, vamos criar uma interface gráfica para mostrar diferentes funcionalidades que podem ser desenvolvidas com o shield TFT.
Lembre-se de adaptá-lo conforme as configurações do seu ecrã.
#include <Adafruit_GFX.h> #include <MCUFRIEND_kbv.h> MCUFRIEND_kbv tft; #include <TouchScreen.h> #include <Fonts/FreeSans9pt7b.h> #include <Fonts/FreeSans12pt7b.h> #include <Fonts/FreeSerif12pt7b.h> #include <FreeDefaultFonts.h> #define MINPRESSURE 200 #define MAXPRESSURE 1000 // ALL Touch panels and wiring is DIFFERENT // copy-paste results from TouchScreen_Calibr_native.ino //3.5 Calibration const int XP = 8, XM = A2, YP = A3, YM = 9; //320x480 ID=0x9486 const int TS_LEFT = 144, TS_RT = 887, TS_TOP = 936, TS_BOT = 87; /*PORTRAIT CALIBRATION 320 x 480 x = map(p.x, LEFT=144, RT=887, 0, 320) y = map(p.y, TOP=936, BOT=87, 0, 480) Touch Pin Wiring XP=8 XM=A2 YP=A3 YM=9 LANDSCAPE CALIBRATION 480 x 320 x = map(p.y, LEFT=936, RT=87, 0, 480) y = map(p.x, TOP=887, BOT=144, 0, 320)*/ //2.8 Calbiration //const int XP=8,XM=A2,YP=A3,YM=9; //240x320 ID=0x9341 //const int TS_LEFT=907,TS_RT=120,TS_TOP=74,TS_BOT=913; /*PORTRAIT CALIBRATION 240 x 320 x = map(p.x, LEFT=907, RT=120, 0, 240) y = map(p.y, TOP=74, BOT=913, 0, 320) Touch Pin Wiring XP=8 XM=A2 YP=A3 YM=9 LANDSCAPE CALIBRATION 320 x 240 x = map(p.y, LEFT=74, RT=913, 0, 320) y = map(p.x, TOP=120, BOT=907, 0, 240)*/ TouchScreen ts = TouchScreen(XP, YP, XM, YM, 300); TSPoint p; Adafruit_GFX_Button on_btn, off_btn, page1_btn, page2_btn, page3_btn; Adafruit_GFX_Button ok_btn, cncl_btn, plus_btn, minus_btn; Adafruit_GFX_Button menu_btn, info_btn, back_btn; int pixel_x, pixel_y; //Touch_getXY() updates global vars // Button calibration int margin = 5; int btnWidth = 100; int btnHeight = 40; int btnY = 200; // Software variable bool enable_nuit = false; int parameter = 50, old_parameter = 50; long temp0 = 60; long temp1 = 25.5; long temp2 = 40; long temp3 = 35.6; #define BLACK 0x0000 #define GREY 0x5555 #define BLUE 0x001F #define RED 0xF800 #define GREEN 0x07E0 #define DARKGREEN 0x05C0 #define CYAN 0x07FF #define MAGENTA 0xF81F #define YELLOW 0xFFE0 #define GOLD 0xDDC0 #define WHITE 0xFFFF enum pageId { MENU, SENSOR, CMD, PARAM, INFO }; unsigned int currentPage = MENU, oldPage = -1; void setup(void) { Serial.begin(9600); //init TFTTouch uint16_t ID = tft.readID(); Serial.print("TFT ID = 0x"); Serial.println(ID, HEX); Serial.println(F("Calibrate for your Touch Panel")); if (ID == 0xD3D3) ID = 0x9486; //for 3.5" TFT LCD Shield , 0x9341 for 2.8" TFT LCD Shield tft.begin(ID); tft.setRotation(1); //0-PORTRAIT 1-PAYSAGE 2-REVERSE PORTRAIT 3-REVERSE PAYSAGE //tft.setFont(&FreeSmallFont); /*if (!SD.begin(SD_CS)) { Serial.println(F("initialization failed!")); return; }*/ currentPage = MENU; // Indicates that we are at Home Screen Serial.println("Home Page"); } bool down ; void loop(void) { switch (currentPage) { case MENU: //Menu page if (currentPage != oldPage) drawMenuScreen(); page1_btn.press(down && page1_btn.contains(pixel_x, pixel_y)); page2_btn.press(down && page2_btn.contains(pixel_x, pixel_y)); page3_btn.press(down && page3_btn.contains(pixel_x, pixel_y)); if (page1_btn.justReleased()) page1_btn.drawButton(); if (page2_btn.justReleased()) page2_btn.drawButton(); if (page3_btn.justReleased()) page3_btn.drawButton(); if (page1_btn.justPressed()) { page1_btn.drawButton(true); currentPage = SENSOR; } if (page2_btn.justPressed()) { page2_btn.drawButton(true); currentPage = CMD; } if (page3_btn.justPressed()) { page3_btn.drawButton(true); currentPage = PARAM; } break; case SENSOR: if (currentPage != oldPage) drawSensorScreen(); readSensor(); updateTemp(); menu_btn.press(down && menu_btn.contains(pixel_x, pixel_y)); info_btn.press(down && info_btn.contains(pixel_x, pixel_y)); if (menu_btn.justReleased()) menu_btn.drawButton(); if (info_btn.justReleased()) info_btn.drawButton(); if (menu_btn.justPressed()) { menu_btn.drawButton(true); currentPage = MENU; } if (info_btn.justPressed()) { info_btn.drawButton(true); currentPage = INFO; } break; case CMD: if (currentPage != oldPage) drawCmdScreen(); on_btn.press(down && on_btn.contains(pixel_x, pixel_y)); off_btn.press(down && off_btn.contains(pixel_x, pixel_y)); back_btn.press(down && back_btn.contains(pixel_x, pixel_y)); if (back_btn.justReleased()) back_btn.drawButton(); if (on_btn.justReleased()) on_btn.drawButton(); if (off_btn.justReleased()) off_btn.drawButton(); if (back_btn.justPressed()) { back_btn.drawButton(true); currentPage = MENU; } if (on_btn.justPressed()) { on_btn.drawButton(true); tft.fillRect(tft.width() / 2. - (btnWidth + 40) / 2, btnY - 4 * margin - (btnHeight) / 2 - (btnHeight + 40), btnWidth + 40, btnHeight + 40, GREEN); Serial.println(F("Set ON")); } if (off_btn.justPressed()) { off_btn.drawButton(true); tft.fillRect(tft.width() / 2. - (btnWidth + 40) / 2, btnY - 4 * margin - (btnHeight) / 2 - (btnHeight + 40), btnWidth + 40, btnHeight + 40, RED); Serial.println(F("Set OFF")); } break; case PARAM: //consigne if (currentPage != oldPage) drawParamScreen(); plus_btn.press(down && plus_btn.contains(pixel_x, pixel_y)); minus_btn.press(down && minus_btn.contains(pixel_x, pixel_y)); ok_btn.press(down && ok_btn.contains(pixel_x, pixel_y)); cncl_btn.press(down && cncl_btn.contains(pixel_x, pixel_y)); if (plus_btn.justReleased()) plus_btn.drawButton(); if (minus_btn.justReleased()) minus_btn.drawButton(); if (ok_btn.justReleased()) ok_btn.drawButton(); if (cncl_btn.justReleased()) cncl_btn.drawButton(); if (plus_btn.justPressed()) { plus_btn.drawButton(true); parameter += 1; Serial.print(F("Consigne : ")); Serial.println(parameter); drawTextInRect(tft.width() / 2., 60 + 3 * 4 + 6 * 8, parameter, 4, RED, BLACK); } if (minus_btn.justPressed()) { minus_btn.drawButton(true); parameter -= 1; Serial.print(F("Consigne : ")); Serial.println(parameter); drawTextInRect(tft.width() / 2., 60 + 3 * 4 + 6 * 8, parameter, 4, RED, BLACK); } if (ok_btn.justPressed()) { ok_btn.drawButton(true); Serial.println(F("Valider")); validateScreen(); delay(1000); currentPage = MENU; } if (cncl_btn.justPressed()) { cncl_btn.drawButton(true); parameter = old_parameter; Serial.println(F("Annule ")); cancelScreen(); delay(1000); currentPage = MENU; } break; case INFO: if (currentPage != oldPage) drawInfoScreen(); if (Touch_getXY()) { currentPage = MENU; } break; } if (oldPage == currentPage){ down = Touch_getXY(); }else{ down=false; } } /************************************************************************************ SCREENS DEFINTION ************************************************************************************/ void drawMenuScreen() { tft.fillScreen(BLACK); tft.setTextSize(2); // Title tft.setTextColor(WHITE, BLACK); tft.setCursor(0, 10); tft.print("Exemple de menu"); // Prints the string on the screen tft.drawLine(0, 32, tft.width() * 0.6, 32, DARKGREEN); // Draws the red line tft.setTextColor(WHITE, BLACK);//((255, 255, 255), (0,0,0)); tft.setCursor(0, 80); tft.setTextColor(GREEN, BLACK);//((255, 255, 255), (0,0,0)); // Button page1_btn.initButton(&tft, tft.width() / 2. , tft.height() / 2. - (1.*btnHeight + margin), 2 * btnWidth, btnHeight, WHITE, GREEN, BLACK, "SENSOR", 2); page2_btn.initButton(&tft, tft.width() / 2., tft.height() / 2., 2 * btnWidth, btnHeight, WHITE, GREEN, BLACK, "COMMAND", 2); page3_btn.initButton(&tft, tft.width() / 2., tft.height() / 2. + (1.*btnHeight + margin), 2 * btnWidth, btnHeight, WHITE, GREEN, BLACK, "PARAMETER", 2); page1_btn.drawButton(false); page2_btn.drawButton(false); page3_btn.drawButton(false); //Button frame tft.drawRoundRect(tft.width() / 2. - 1.5 * btnWidth, tft.height() / 2. - (1.5 * btnHeight + 2 * margin), 2 * btnWidth + btnWidth, 3 * btnHeight + 4 * margin, 10, GREEN); oldPage = currentPage; } void readSensor() { temp0 = temp0 + random(-25, 25) / 10; temp1 = temp1 + random(-25, 25) / 10; temp2 = temp2 + random(-25, 25) / 10; temp3 = temp3 + random(-25, 25) / 10; } void drawSensorScreen() { tft.fillScreen(BLACK); tft.drawLine(tft.width() / 2., 0, tft.width() / 2., tft.height(), WHITE); tft.drawLine(0, tft.height() / 2., tft.width(), tft.height() / 2., WHITE); updateTemp(); tft.setTextSize(1); // bouton centré X,Y menu_btn.initButton(&tft, tft.width() / 2. - btnWidth - margin , tft.height() - btnHeight / 2., btnWidth, btnHeight, WHITE, GREY, BLACK, "MENU", 2); info_btn.initButton(&tft, tft.width() / 2. + btnWidth + margin, tft.height() - btnHeight / 2., btnWidth, btnHeight, WHITE, GREY, BLACK, "INFO", 2); menu_btn.drawButton(false); info_btn.drawButton(false); oldPage = currentPage; } void updateTemp() { //temp1 if (parameter < temp0) { //(abs(parameter-temp0)<1){ drawTextInRect(tft.width() / 4., tft.height() / 4., temp0, 5, GREEN, 255); } else { drawTextInRect(tft.width() / 4., tft.height() / 4., temp0, 5, RED, 255); } drawTextInRect(3 * tft.width() / 4., tft.height() / 4., temp1, 5, RED, 255); drawTextInRect(tft.width() / 4., 3 * tft.height() / 4., temp2, 5, RED, 255); drawTextInRect(3 * tft.width() / 4., 3 * tft.height() / 4., temp3, 5, RED, 255); } void drawCmdScreen() { tft.setRotation(1); //PORTRAIT tft.setTextSize(1); tft.fillScreen(BLACK); back_btn.initButton(&tft, 60 , 20, btnWidth, btnHeight, BLACK, BLACK, WHITE, "<- Back", 2); // bouton centré X,Y on_btn.initButton(&tft, tft.width() / 2. - btnWidth / 2. , btnY, btnWidth, btnHeight, WHITE, GREEN, BLACK, "ON", 2); off_btn.initButton(&tft, tft.width() / 2. + btnWidth / 2. + margin, btnY, btnWidth, btnHeight, WHITE, RED, BLACK, "OFF", 2); back_btn.drawButton(false); on_btn.drawButton(false); off_btn.drawButton(false); tft.fillRect(tft.width() / 2. - (btnWidth + 40) / 2, btnY - 4 * margin - (btnHeight) / 2 - (btnHeight + 40), btnWidth + 40, btnHeight + 40, RED); oldPage = currentPage; } void validateScreen() { tft.setRotation(1); tft.fillScreen(BLACK); tft.setTextSize(5); tft.setTextColor(BLACK, GREEN); tft.setCursor(tft.width() / 2. - 6 * 6 * 4, tft.height() / 2. - 1 * 6); tft.print(" VALIDE "); } void cancelScreen() { tft.setRotation(1); tft.fillScreen(BLACK); tft.setTextSize(5); tft.setTextColor(BLACK, RED); tft.setCursor(tft.width() / 2. - 6 * 6 * 4, tft.height() / 2. - 1 * 6); tft.print(" ANNULE "); } void drawParamScreen() { tft.setRotation(1); tft.fillScreen(BLACK); //Title tft.setTextSize(3); tft.setTextColor(WHITE, BLACK); tft.setCursor(tft.width() / 2. - 9 * 3 * 3, 50); tft.print("Parameter"); ok_btn.initButton(&tft, 2 + btnWidth / 2., btnHeight / 2. + margin, btnWidth, btnHeight, WHITE, DARKGREEN, BLACK, "Valider", 2); cncl_btn.initButton(&tft, tft.width() - btnWidth / 2 - 2, btnHeight / 2. + margin, btnWidth, btnHeight, WHITE, RED, BLACK, "Annuler", 2); ok_btn.drawButton(false); cncl_btn.drawButton(false); drawTextInRect(tft.width() / 2., 60 + 3 * 4 + 6 * 8, parameter, 4, RED, BLACK); plus_btn.initButton(&tft, tft.width() / 2. - btnWidth / 2. , 60 + 3 * 4 + 6 * 8 + (btnWidth - 30), btnWidth - 20, btnWidth - 30, WHITE, GREEN, BLACK, "+", 5); minus_btn.initButton(&tft, tft.width() / 2. + btnWidth / 2. + margin, 60 + 3 * 4 + 6 * 8 + (btnWidth - 30), btnWidth - 20, btnWidth - 30, WHITE, GREEN, BLACK, "-", 5); plus_btn.drawButton(false); minus_btn.drawButton(false); oldPage = currentPage; } void drawInfoScreen() { tft.setRotation(1); tft.fillScreen(BLACK);//(100, 155, 203) tft.drawRoundRect(10, 50, tft.width() - 20, tft.height() - 60, 5, GREEN); //tft.fillRect (10, 10, 60, 36); tft.setTextSize(2); tft.setTextColor(WHITE, BLACK); tft.setCursor(70, 18); tft.print("Information sur l'exemple"); tft.setTextSize(2); tft.setTextColor(WHITE, BLACK); tft.setCursor(25, 80); tft.print("En cas de probleme avec ce tutoriel,\n n'hesitez pas a nous contacter"); tft.setCursor(20, 245); tft.print("www.aranacorp.com" ); oldPage = currentPage; } /************************************************************************************ UTILITY FUNCTION *************************************************************************************/ void drawTextInRect(int x, int y, long temp, int tsize, unsigned int fColor, unsigned int bColor) { int marg = 10; char buf[12]; int nbChar = strlen(itoa(temp, buf, 10)) + 2; if (bColor != 255) tft.fillRect(x - nbChar * 3 * tsize - marg, y - nbChar * 1 * tsize - marg, nbChar * 6 * tsize + 2 * marg, nbChar * 2 * tsize + 2 * marg, bColor); tft.setTextSize(tsize); tft.setTextColor(fColor, BLACK); //tft.setCursor(x-strlen(*text)*3*tsize+marg, y+rheight/2.+marg); tft.setCursor(x - nbChar * 3 * tsize, y - nbChar * 1 * tsize); tft.print(temp); //while(*text) tft.print(*text++); tft.write(0xF7); tft.print("C"); } bool Touch_getXY(void) { p = ts.getPoint(); pinMode(YP, OUTPUT); //restore shared pins pinMode(XM, OUTPUT); digitalWrite(YP, HIGH); digitalWrite(XM, HIGH); bool pressed = (p.z > MINPRESSURE && p.z < MAXPRESSURE); if (pressed) { if (tft.width() <= tft.height()) { //Portrait pixel_x = map(p.x, TS_LEFT, TS_RT, 0, tft.width()); //.kbv makes sense to me pixel_y = map(p.y, TS_TOP, TS_BOT, 0, tft.height()); } else { pixel_x = map(p.y, TS_TOP, TS_BOT, 0, tft.width()); pixel_y = map(p.x, TS_RT, TS_LEFT, 0, tft.height()); } } return pressed; }
Aplicações
- Criar uma interface gráfica para controlar o seu projeto Arduino
Fontes
- https://www.arduino.cc/en/reference/SD
- https://github.com/adafruit/Adafruit-GFX-Library
- https://github.com/prenticedavid/MCUFRIEND_kbv
Retrouvez nos tutoriels et d’autres exemples dans notre générateur automatique de code
La Programmerie