Difference between revisions of "Domotica Arduino Integrazione Display TFT LCD"
From Aino Wiki
(→Sketch utili) |
|||
| Line 1,669: | Line 1,669: | ||
Copiato da [https://github.com/Bodmer/TFT_ILI9341/blob/master/examples/TFT_Terminal/TFT_Terminal.ino GitHub BodManer] | Copiato da [https://github.com/Bodmer/TFT_ILI9341/blob/master/examples/TFT_Terminal/TFT_Terminal.ino GitHub BodManer] | ||
<syntaxhighlight lang="csharp"> | <syntaxhighlight lang="csharp"> | ||
| − | |||
/************************************************************* | /************************************************************* | ||
This sketch implements a simple serial receive terminal | This sketch implements a simple serial receive terminal | ||
| Line 1,824: | Line 1,823: | ||
tft.writedata(vsp); | tft.writedata(vsp); | ||
} | } | ||
| − | |||
</syntaxhighlight> | </syntaxhighlight> | ||
| + | ===Paginazione del testo di log=== | ||
| + | Il seguente si presta alla scrittura del testo sul display come una sequenza di righe, come in una applicazione di logging o una chat, è tarato per la dimensione minima del testo ovvero 1, sono previste 30 righe e nel caso nel testo ci sia un riotrno accapo questo verrà considerato nel conteggio del rigo corrente. Quando il testo raggiunge il massimo rigo il display viene pulito e si riscrive sul primo rigo e così via. | ||
| + | <syntaxhighlight lang="csharp"> | ||
| + | #include <Arduino.h> | ||
| + | #include "SPI.h" | ||
| + | #include "Adafruit_GFX.h" | ||
| + | #include "Adafruit_ILI9341.h" | ||
| + | //---------------------Costanti per il display TFT--------------------- | ||
| + | #define TS_CS 7 // Chip Select pin for the touch screen | ||
| + | #define TFT_RST 8 // Reset pin | ||
| + | #define TFT_DC 9 // Data/Command pin | ||
| + | #define TFT_CS 10 // Slave select o Chip Select (CS) pin | ||
| + | #define TFT_MOSI 11 | ||
| + | #define TFT_MISO 12 | ||
| + | #define TFT_CLK 13 | ||
| + | |||
| + | const uint8_t m_rotationLandscapeInv = 3; //Rotazione display landscape | ||
| + | const uint8_t m_maxRoxsTxt1 = 30; //Numero massimo di righe di testo con dimensione 1 | ||
| + | |||
| + | long m_lastUpdateSmartPhone = 0; | ||
| + | int m_intCounter = 0; | ||
| + | String m_strCount = ""; | ||
| + | String m_strMessage = ""; | ||
| + | String m_strTmp = ""; | ||
| + | int16_t m_tftWidth = 0, m_tftHeight = 0; //Dimensioni schermo TFT, valorizzate in setup() | ||
| + | uint8_t m_currRow = 0; //Riga corrente per stampa testo, supponendo di dimensione 1, quindi max 30 righe (m_maxRoxsTxt1) per evitare di sovrascrivere il testo precedente | ||
| + | |||
| + | //Per il display TFT | ||
| + | Adafruit_ILI9341 m_tft = Adafruit_ILI9341(TFT_CS, TFT_DC, TFT_RST); | ||
| + | |||
| + | //---------------------- PROTOTIPI Funzioni globali ---------------------------- | ||
| + | void Println(String text, byte textSize, uint16_t colorText); | ||
| + | void PrintTFT(int x, int y, const char* text, byte textSize, uint16_t colorText); | ||
| + | void PrintTFT(int x, int y, String text, byte textSize, uint16_t colorText); | ||
| + | void PrintTFTln(String text, byte textSize, uint16_t colorText); | ||
| + | //---------------------- END PROTOTIPI Funzioni globali ------------------------ | ||
| + | |||
| + | |||
| + | void setup() { | ||
| + | Serial.begin(9600); | ||
| + | |||
| + | // Si deselezionano tutti i dispositivi SPI | ||
| + | pinMode(TFT_CS, OUTPUT); // pin 10, Chip Select for TFT display | ||
| + | pinMode(7, OUTPUT); // Slave Select for second SPI device il touch screen | ||
| + | digitalWrite(TFT_CS, HIGH); // pin 10, Chip Select for TFT display | ||
| + | digitalWrite(7, HIGH); // Slave Select for second SPI device il touch screen | ||
| + | |||
| + | m_tft.begin(); | ||
| + | |||
| + | m_tft.setRotation(m_rotationLandscapeInv); | ||
| + | m_tft.fillScreen(ILI9341_BLACK); | ||
| + | m_tftWidth = m_tft.width(); | ||
| + | m_tftHeight = m_tft.height(); | ||
| + | |||
| + | //Si attende che la seriale sia pronta, con un timeout di 2 secondi | ||
| + | //altrimenti se se ci fosse l'istruzione while (!Serial) e non si avviasse | ||
| + | //il Monitor Seriale l'applicazione andrebbe in loop infinito | ||
| + | unsigned long previousMillis = millis(); | ||
| + | unsigned long currentMillis = millis(); | ||
| + | while (!Serial | ||
| + | && (currentMillis - previousMillis <= 2000)) { //timeout 2s per evitare di restare bloccati | ||
| + | currentMillis = millis(); | ||
| + | } | ||
| + | |||
| + | m_strMessage = "fine setup()"; | ||
| + | Println(m_strMessage, 1, ILI9341_PURPLE); | ||
| + | } | ||
| + | |||
| + | void loop() { | ||
| + | //Scrive il contatore ogni secondo | ||
| + | if (millis() - m_lastUpdateSmartPhone > 1000) { | ||
| + | m_lastUpdateSmartPhone = millis(); | ||
| + | m_intCounter++; | ||
| + | m_strCount = String(m_intCounter); | ||
| + | m_strMessage = "Conteggio: " + m_strCount; | ||
| + | Println(m_strMessage, 1, ILI9341_GREEN); | ||
| + | } | ||
| + | } | ||
| + | |||
| + | void Println(String text, byte textSize, uint16_t colorText) { | ||
| + | PrintTFTln(text, textSize, colorText); | ||
| + | if (Serial) { | ||
| + | Serial.println(text); | ||
| + | } | ||
| + | } | ||
| + | |||
| + | void PrintTFT(int x, int y, const char* text, byte textSize, uint16_t colorText) { | ||
| + | m_tft.setCursor(x, y); | ||
| + | m_tft.setTextColor(colorText); | ||
| + | m_tft.setTextSize(textSize); | ||
| + | m_tft.print(text); | ||
| + | } | ||
| + | |||
| + | void PrintTFT(int x, int y, String text, byte textSize, uint16_t colorText) { | ||
| + | if (x == -1 && y == -1) { | ||
| + | m_tft.setCursor(x, y); | ||
| + | } | ||
| + | m_tft.setTextColor(colorText); | ||
| + | m_tft.setTextSize(textSize); | ||
| + | m_tft.print(text); | ||
| + | } | ||
| + | |||
| + | void PrintTFTln(String text, byte textSize, uint16_t colorText) { | ||
| + | if (text.indexOf('\n') != -1) { | ||
| + | m_currRow++; | ||
| + | } | ||
| + | m_tft.setTextColor(colorText); | ||
| + | m_tft.setTextSize(textSize); | ||
| + | m_tft.println(text); | ||
| + | m_currRow++; | ||
| + | if (m_currRow >= m_maxRoxsTxt1) { | ||
| + | m_currRow = 0; | ||
| + | m_tft.fillScreen(ILI9341_BLACK); // Pulisce lo schermo quando si raggiunge il numero massimo di righe | ||
| + | m_tft.setCursor(0, 0); // Torna alla prima riga dopo aver pulito lo schermo | ||
| + | } | ||
| + | } | ||
| + | </syntaxhighlight> | ||
==Lettore SSD== | ==Lettore SSD== | ||
Latest revision as of 08:39, 4 March 2026
Contents
LCD TFT SPI - ILI9341 LCD with XPT2046 Touch
- Tutorial fondamentale: bytesnbits.co.uk;
- Video diretto YT.
Il display da 3.2" con risoluzione è 240x320px ha due componenti fondamentali: il controller grafico ILI9341 e quello del touchscreen di tipo resistivo XPT2046 (di XPTek).
Occorrerebbe approfondire il protocollo di interfaccia seriale SPI (ideato inizialmente da Motorola) e che si contrappone all' I2C:
elettronica-tech.it.
IMPORTANTE come da specifiche del protocollo di interfaccia SPI il collegamento tra il display (slave) e Arduino (master) non può esser lungo, ad es. collegando un cavo maschio femmina da 20cm ho sperimentato che il display, per quanto acceso ed illuminato, non funzionasse! Display LCD TFT SPI - ILI9341 LCD with XPT2046 Touch acquistato su Temu a 13€:
Progetto
NOTA quanto segue è una adattamento\copia di quanto suggerito qui (bytesnbits.co.uk).Configurazione del bus SPI:
PS manca il collegamento giallo tra il Pin digitale 7 con la funzione di Slave Select sul touchscreen.
Tabella dei collegamenti:
| Funzione collegamento | Arduino | TFT | Touch |
|---|---|---|---|
| SCK Serial Clock |
Pin 13 | SCK | T_CLK |
| MISO Master Input, Slave Output |
Pin 12 | SDO (MISO) | T_DO |
|
MOSI |
Pin 11 | SDI (MOSI) | T_DIN |
| SS Slave Select |
Pin 10 | CS | |
| DC Data / Command |
Pin 9 | DC | |
| RESET Reset |
Pin 8 | RESET | |
|
SS |
Pin 7 | T_CS |
Tre collegamenti essenziali:
NOTA, il display funziona con logica e tensione a 3.3V:
Dettaglio progetto:
Sistemazione su breadboard (design con Frizing):
Mia implementazione:
Sketch per display
Sul fronte della programmazione, sketch, utilizzeremo la libreria Adafruit ILI9341 per gestire la comunicazione di basso livello con il pannello LCD.
Librerie da installare:
- Adafruit ILI9341 (nel tutorial si parla della 1.5.6). GitHub: Adafruit_ILI9341
- Adafruit GFX Library (nel tutorial si parla della 1.10.1). GitHub: Adafruit-GFX-Library. Doc. primiteive [1]
Usando VS Code e PatformIO le librerie ci sono e si ricercano ed aggiungono normalmente.
Sketch di esempio copiato (dalla libreria "Adafruit ILI9341") adattato in base al tutorial e corretto da un baco:
/*************************************************** This is our GFX example for the Adafruit ILI9341 Breakout and Shield ----> http://www.adafruit.com/products/1651 Written by Limor Fried/Ladyada for Adafruit Industries. MIT license, all text above must be included in any redistribution ****************************************************/ #include <Arduino.h> #include "SPI.h" #include "Adafruit_GFX.h" #include "Adafruit_ILI9341.h" // For the Adafruit shield, these are the default. #define TFT_RST 8 // Reset pin #define TFT_DC 9 // Data/Command pin #define TFT_CS 10 // Slave select o Chip Select (CS) pin Adafruit_ILI9341 tft = Adafruit_ILI9341(TFT_CS, TFT_DC, TFT_RST); // If using the breakout, change pins as desired //Adafruit_ILI9341 tft = Adafruit_ILI9341(TFT_CS, TFT_DC, TFT_MOSI, TFT_CLK, TFT_RST, TFT_MISO); //Contratto funzioni locali unsigned long testFillScreen(void); unsigned long testText(void); unsigned long testLines(uint16_t color); unsigned long testFastLines(uint16_t color1, uint16_t color2); unsigned long testRects(uint16_t color); unsigned long testFilledRects(uint16_t color1, uint16_t color2); unsigned long testFilledCircles(uint8_t radius, uint16_t color); unsigned long testCircles(uint8_t radius, uint16_t color); unsigned long testTriangles(void); unsigned long testFilledTriangles(void); unsigned long testRoundRects(void); unsigned long testFilledRoundRects(void); void setup() { Serial.begin(9600); Serial.println("ILI9341 Test!"); // Si deselezionano tutti i dispositivi SPI pinMode(TFT_CS, OUTPUT); // pin 10, Chip Select for TFT display pinMode(7, OUTPUT); // Slave Select for second SPI device il touch screen digitalWrite(TFT_CS, HIGH); // pin 10, Chip Select for TFT display digitalWrite(7, HIGH); // Slave Select for second SPI device il touch screen tft.begin(); delay(4000); //Per darmi modo di aprire il monitor seriale e vedere quanto segue Serial.println(F("[Dalla funzione setup()] Starting...")); // read diagnostics (optional but can help debug problems) uint8_t x = tft.readcommand8(ILI9341_RDMODE); Serial.print("Display Power Mode: 0x"); Serial.println(x, HEX); x = tft.readcommand8(ILI9341_RDMADCTL); Serial.print("MADCTL Mode: 0x"); Serial.println(x, HEX); x = tft.readcommand8(ILI9341_RDPIXFMT); Serial.print("Pixel Format: 0x"); Serial.println(x, HEX); x = tft.readcommand8(ILI9341_RDIMGFMT); Serial.print("Image Format: 0x"); Serial.println(x, HEX); x = tft.readcommand8(ILI9341_RDSELFDIAG); Serial.print("Self Diagnostic: 0x"); Serial.println(x, HEX); Serial.println(F("Benchmark Time (microseconds)")); delay(10); Serial.print(F("Screen fill ")); Serial.println(testFillScreen()); delay(500); Serial.print(F("Text ")); Serial.println(testText()); delay(3000); Serial.print(F("Lines ")); Serial.println(testLines(ILI9341_CYAN)); delay(500); Serial.print(F("Horiz/Vert Lines ")); Serial.println(testFastLines(ILI9341_RED, ILI9341_BLUE)); delay(500); Serial.print(F("Rectangles (outline) ")); Serial.println(testRects(ILI9341_GREEN)); delay(500); Serial.print(F("Rectangles (filled) ")); Serial.println(testFilledRects(ILI9341_YELLOW, ILI9341_MAGENTA)); delay(500); Serial.print(F("Circles (filled) ")); Serial.println(testFilledCircles(10, ILI9341_MAGENTA)); Serial.print(F("Circles (outline) ")); Serial.println(testCircles(10, ILI9341_WHITE)); delay(500); Serial.print(F("Triangles (outline) ")); Serial.println(testTriangles()); delay(500); Serial.print(F("Triangles (filled) ")); Serial.println(testFilledTriangles()); delay(500); Serial.print(F("Rounded rects (outline) ")); Serial.println(testRoundRects()); delay(500); Serial.print(F("Rounded rects (filled) ")); Serial.println(testFilledRoundRects()); delay(500); Serial.println(F("[Dalla funzione setup()] ... Done!")); } void loop(void) { for(uint8_t rotation=0; rotation<4; rotation++) { tft.setRotation(rotation); testText(); delay(1000); } } unsigned long testFillScreen() { unsigned long start = micros(); tft.fillScreen(ILI9341_BLACK); yield(); tft.fillScreen(ILI9341_RED); yield(); tft.fillScreen(ILI9341_GREEN); yield(); tft.fillScreen(ILI9341_BLUE); yield(); tft.fillScreen(ILI9341_BLACK); yield(); return micros() - start; } unsigned long testText() { tft.fillScreen(ILI9341_BLACK); unsigned long start = micros(); tft.setCursor(0, 0); tft.setTextColor(ILI9341_WHITE); tft.setTextSize(1); tft.println("Ciao mondo cattivo!"); tft.setTextColor(ILI9341_YELLOW); tft.setTextSize(2); tft.println(1234.56); tft.setTextColor(ILI9341_RED); tft.setTextSize(3); tft.println(0xDEADBEEF, HEX); tft.println(); tft.setTextColor(ILI9341_GREEN); tft.setTextSize(5); tft.println("Gruppo di dimensione 5"); tft.setTextSize(2); tft.println("I implore thee,"); tft.setTextSize(1); tft.println("my foonting turlingdromes."); tft.println("And hooptiously drangle me"); tft.println("with crinkly bindlewurdles,"); tft.println("Or I will rend thee"); tft.println("in the gobberwarts"); tft.println("with my blurglecruncheon,"); tft.println("see if I don't!"); tft.println("......... fine della strana poesia......"); return micros() - start; } unsigned long testLines(uint16_t color) { unsigned long start, t; int x1, y1, x2, y2, w = tft.width(), h = tft.height(); tft.fillScreen(ILI9341_BLACK); yield(); x1 = y1 = 0; y2 = h - 1; start = micros(); for(x2=0; x2<w; x2+=6) tft.drawLine(x1, y1, x2, y2, color); x2 = w - 1; for(y2=0; y2<h; y2+=6) tft.drawLine(x1, y1, x2, y2, color); t = micros() - start; // fillScreen doesn't count against timing yield(); tft.fillScreen(ILI9341_BLACK); yield(); x1 = w - 1; y1 = 0; y2 = h - 1; start = micros(); for(x2=0; x2<w; x2+=6) tft.drawLine(x1, y1, x2, y2, color); x2 = 0; for(y2=0; y2<h; y2+=6) tft.drawLine(x1, y1, x2, y2, color); t += micros() - start; yield(); tft.fillScreen(ILI9341_BLACK); yield(); x1 = 0; y1 = h - 1; y2 = 0; start = micros(); for(x2=0; x2<w; x2+=6) tft.drawLine(x1, y1, x2, y2, color); x2 = w - 1; for(y2=0; y2<h; y2+=6) tft.drawLine(x1, y1, x2, y2, color); t += micros() - start; yield(); tft.fillScreen(ILI9341_BLACK); yield(); x1 = w - 1; y1 = h - 1; y2 = 0; start = micros(); for(x2=0; x2<w; x2+=6) tft.drawLine(x1, y1, x2, y2, color); x2 = 0; for(y2=0; y2<h; y2+=6) tft.drawLine(x1, y1, x2, y2, color); yield(); return micros() - start; } unsigned long testFastLines(uint16_t color1, uint16_t color2) { unsigned long start; int x, y, w = tft.width(), h = tft.height(); tft.fillScreen(ILI9341_BLACK); start = micros(); for(y=0; y<h; y+=5) tft.drawFastHLine(0, y, w, color1); for(x=0; x<w; x+=5) tft.drawFastVLine(x, 0, h, color2); return micros() - start; } unsigned long testRects(uint16_t color) { unsigned long start; int n, i, i2, cx = tft.width() / 2, cy = tft.height() / 2; tft.fillScreen(ILI9341_BLACK); n = min(tft.width(), tft.height()); start = micros(); for(i=2; i<n; i+=6) { i2 = i / 2; tft.drawRect(cx-i2, cy-i2, i, i, color); } return micros() - start; } unsigned long testFilledRects(uint16_t color1, uint16_t color2) { unsigned long start, t = 0; int n, i, i2, cx = tft.width() / 2 - 1, cy = tft.height() / 2 - 1; tft.fillScreen(ILI9341_BLACK); n = min(tft.width(), tft.height()); for(i=n; i>0; i-=6) { i2 = i / 2; start = micros(); tft.fillRect(cx-i2, cy-i2, i, i, color1); t += micros() - start; // Outlines are not included in timing results tft.drawRect(cx-i2, cy-i2, i, i, color2); yield(); } return t; } unsigned long testFilledCircles(uint8_t radius, uint16_t color) { unsigned long start; int x, y, w = tft.width(), h = tft.height(), r2 = radius * 2; tft.fillScreen(ILI9341_BLACK); start = micros(); for(x=radius; x<w; x+=r2) { for(y=radius; y<h; y+=r2) { tft.fillCircle(x, y, radius, color); } } return micros() - start; } unsigned long testCircles(uint8_t radius, uint16_t color) { unsigned long start; int x, y, r2 = radius * 2, w = tft.width() + radius, h = tft.height() + radius; // Screen is not cleared for this one -- this is // intentional and does not affect the reported time. start = micros(); for(x=0; x<w; x+=r2) { for(y=0; y<h; y+=r2) { tft.drawCircle(x, y, radius, color); } } return micros() - start; } unsigned long testTriangles() { unsigned long start; int n, i, cx = tft.width() / 2 - 1, cy = tft.height() / 2 - 1; tft.fillScreen(ILI9341_BLACK); n = min(cx, cy); start = micros(); for(i=0; i<n; i+=5) { tft.drawTriangle( cx , cy - i, // peak cx - i, cy + i, // bottom left cx + i, cy + i, // bottom right tft.color565(i, i, i)); } return micros() - start; } unsigned long testFilledTriangles() { unsigned long start, t = 0; int i, cx = tft.width() / 2 - 1, cy = tft.height() / 2 - 1; tft.fillScreen(ILI9341_BLACK); start = micros(); for(i=min(cx,cy); i>10; i-=5) { start = micros(); tft.fillTriangle(cx, cy - i, cx - i, cy + i, cx + i, cy + i, tft.color565(0, i*10, i*10)); t += micros() - start; tft.drawTriangle(cx, cy - i, cx - i, cy + i, cx + i, cy + i, tft.color565(i*10, i*10, 0)); yield(); } return t; } unsigned long testRoundRects() { unsigned long start; int w, i, i2, cx = tft.width() / 2 - 1, cy = tft.height() / 2 - 1; tft.fillScreen(ILI9341_BLACK); w = min(tft.width(), tft.height()); start = micros(); for(i=0; i<w; i+=6) { i2 = i / 2; tft.drawRoundRect(cx-i2, cy-i2, i, i, i/8, tft.color565(i, 0, 0)); } return micros() - start; } unsigned long testFilledRoundRects() { unsigned long start; int i, i2, cx = tft.width() / 2 - 1, cy = tft.height() / 2 - 1; tft.fillScreen(ILI9341_BLACK); start = micros(); for(i=min(tft.width(), tft.height()); i>20; i-=6) { i2 = i / 2; tft.fillRoundRect(cx-i2, cy-i2, i, i, i/8, tft.color565(0, i, 0)); yield(); } return micros() - start; }
Sketch per touchscreen
Per testare il touchscreen, si procede con un nuovo progetto, si installa la libreria:
- XPT2046 library, al momento in elenco si trova con "XPT2046_Touchscreen" by Paul Stoffregen. GitHub: XPT2046_Touchscreen.
Si può usare il codice di esempio del file "TouchTestIRQ.ino" che si trova su GitHub della stessa libreria.
Questo programmino, semplicemente restituisce sul Serial Monitor: la pressione esercitata sullo schermo e le coordinate X ed Y in pixel della selezione sullo schermo!
NOTE
- vanno fatte delle modifiche sullo sketch originale, si cambia il pin ChipSelect da 8 (assegnato al reset, vedasi cablatura sulla breadboard) a 7, nel setup si imposta l'uso dei PIN 10 e 7;
- la velocità in bau della seriale deve essere impostata a 38400.
#include <Arduino.h> #include <XPT2046_Touchscreen.h> #include <SPI.h> #define CS_PIN 7 //Chip select // MOSI=11, MISO=12, SCK=13 // The TIRQ interrupt signal must be used for this example. #define TIRQ_PIN 2 XPT2046_Touchscreen ts(CS_PIN); // Param 2 - ULL - Ovvero no interrupts //XPT2046_Touchscreen ts(CS_PIN, TIRQ_PIN); // Param 2 - Touch IRQ Pin - interrupt enabled polling void setup() { Serial.begin(38400); // Deselect ALL SPI devices pinMode(10, OUTPUT); pinMode(7, OUTPUT); digitalWrite(10, HIGH); digitalWrite(7, HIGH); Serial.println("Premere lo schermo del Touchscreen si restituiranno: pressione e coordinate X e Y."); ts.begin(); ts.setRotation(1); while (!Serial && (millis() <= 1000)); } void loop() { // tirqTouched() is much faster than touched(). For projects where other SPI chips // or other time sensitive tasks are added to loop(), using tirqTouched() can greatly // reduce the delay added to loop() when the screen has not been touched. if (ts.tirqTouched()) { if (ts.touched()) { TS_Point p = ts.getPoint(); Serial.print("Pressione = "); Serial.print(p.z); Serial.print(", x = "); Serial.print(p.x); Serial.print(", y = "); Serial.print(p.y); delay(30); Serial.println(); } } }
NOTA Per rilevare il tocco sullo schermo, si può usare direttamente la funzione ts.touched() (vedere lo sketch di sopra) ma non garantisce una corretta rilevazione e la libreria infatti suggerisce quanto segue:
tirqTouched() is much faster than touched().
For projects where other SPI chips or other time sensitive tasks are added to loop(), using
tirqTouched() can greatly reduce the delay added to loop() when the screen has not been touched.
Output, come da VS Code e estensione SERIAL MONITOR:
Un gioco: Arcanoid
NOTA!!! Il codice del seguente gioco è di Bob, del sito Bytes N bits, ho fatto delle piccole correzioni ma sono GRATO PROFONDAMENTE a questo blogger che gratuitamente e generosamente ha condiviso con TUTTI.E' implementato usando VS Code con estensione PlatformIO, ho dovuto aggiungere le funzioni prototipo in testa e del codice di Debug... ATTENZIONE il bus che collega il display DEVE esser corto altrimenti lo schermo rimarrà BIANCO!
Articoli di riferimento (da Bytes N Bits):
Perchè si calibra
Per poter lavorare con le coordinate usate nell'applicazione occorrerà una calibrazione dello schermo ovvero calcoalre una corrispondenza approssimata tra quanto risulta al touchscreen resistivo e quanto risulta al display LCD, i due sono totalmente separati e non c'è corrispondenza esatta.
In parole povere questa necessità deriva dalla teconologia del touchscreen resistivo (indipendente dallo schermo LCD), il calcolo della posizione deriva da due numeri associato ad un coprischermo che quando vien toccato, questi due numeri sono la letture di due resistenze, una per le ascisse x del punto di contatto ed una per le ordinate y dello stesso punto.
Particolare della funzione di calibrazione:
#include <Arduino.h> #include "SPI.h" #include "Adafruit_ILI9341.h" #include "XPT2046_Touchscreen.h" Adafruit_ILI9341 m_tft = Adafruit_ILI9341(TFT_CS, TFT_DC, TFT_RST); XPT2046_Touchscreen m_ts(TS_CS); int16_t m_tftWidth = 0, m_tftHeight = 0; // Dimensioni schermo TFT // Variabili calibrate per il touch screen: float m_xCalM = 0.0, m_yCalM = 0.0; float m_xCalC = 0.0, m_yCalC = 0.0; void setup() { //...etc CalibrateTouchScreen(); //...etc } void CalibrateTouchScreen(){ TS_Point p; int16_t x1,y1,x2,y2; // Coordinate lette dal touchscreen in base ai valori dei RESISTORI! const int16_t c_whPlus = 20; // Ampiezza del + disegnato sullo schermo per la calibrazione if (m_isDebug) {} Serial.println("Calibrating touch screen..."); Serial.print("Height: ");Serial.print(m_tftHeight); Serial.print(" x Width: ");Serial.println(m_tftWidth); Serial.println("Touch the corners as indicated to calibrate the touch screen..."); m_tft.fillScreen(ILI9341_BLACK); while(m_ts.touched()); // In realtà sembra inutile //Disegna un + in alto a SX m_tft.drawFastHLine(10,20,c_whPlus,ILI9341_RED); //Linea oriziontale del + m_tft.drawFastVLine(20,10,c_whPlus,ILI9341_RED); //Linea verticale del + //Attende che l'utente tocchi lo schermo per poi prenderne la posizione while(!m_ts.touched()); // ! p = m_ts.getPoint(); x1 = p.x; // Valore della resistenza sulle ascisse y1 = p.y; // Valore della resistenza sulle ascisse m_tft.drawFastHLine(10,20,c_whPlus,ILI9341_BLACK); // Cancella il + m_tft.drawFastVLine(20,10,c_whPlus,ILI9341_BLACK); Serial.println("Touch the corners bottom right on the screen..."); delay(500); while(m_ts.touched()); // In realtà sembra inutile //Disegna un + in basso a DX m_tft.drawFastHLine(m_tftWidth - 30,m_tftHeight - 20,c_whPlus,ILI9341_RED); m_tft.drawFastVLine(m_tftWidth - 20,m_tftHeight - 30,c_whPlus,ILI9341_RED); //Attende che l'utente tocchi lo schermo per poi prenderne la posizione while(!m_ts.touched()); // ! p = m_ts.getPoint(); x2 = p.x; y2 = p.y; m_tft.drawFastHLine(m_tftWidth - 30,m_tftHeight - 20,c_whPlus,ILI9341_BLACK); // Cancella il + m_tft.drawFastVLine(m_tftWidth - 20,m_tftHeight - 30,c_whPlus,ILI9341_BLACK); // ********************************************************** // ! Calcola i coefficienti di trasformazione ! // ********************************************************** const int16_t c_BothXMargin = 40; //ex 40 const int16_t c_BothYMargin = 40; //ex 40 const float c_TouchXMargin = 20.0; // Ex 20.0 Margine in pixel da considerare sul touch screen const float c_TouchYMargin = 20.0; // Ex 20.0 Margine in pixel da considerare sul touch screen int16_t xDist = m_tftWidth - c_BothXMargin; int16_t yDist = m_tftHeight - c_BothYMargin; // translate in form pos = m x val + c // x m_xCalM = (float)xDist / (float)(x2 - x1); m_xCalC = c_TouchXMargin - ((float)x1 * m_xCalM); // y m_yCalM = (float)yDist / (float)(y2 - y1); m_yCalC = c_TouchYMargin - ((float)y1 * m_yCalM); Serial.print("(x1 = ");Serial.print(x1); Serial.print(", y1 = ");Serial.print(y1); Serial.print(") - (x2 = ");Serial.print(x2); Serial.print(", y2 = ");Serial.print(y2);Serial.println(")"); Serial.print("m_xCalM = ");Serial.print(m_xCalM); Serial.print(", m_xCalC = ");Serial.print(m_xCalC); Serial.print(" - m_yCalM = ");Serial.print(m_yCalM); Serial.print(", m_yCalC = ");Serial.println(m_yCalC); Serial.println("Calibration complete!"); }
Sketch
#include "SPI.h" #include "Adafruit_GFX.h" #include "Adafruit_ILI9341.h" #include "XPT2046_Touchscreen.h" #include "Math.h" // function declarations boolean checkCollision(int x1, int y1, int width1, int height1, int x2, int y2, int width2, int height2); // For the Adafruit shield, these are the default. #define TFT_CS 10 #define TFT_DC 9 #define TFT_MOSI 11 #define TFT_CLK 13 #define TFT_RST 8 #define TFT_MISO 12 #define TS_CS 7 #define ROTATION 3 // Landscape // Use hardware SPI (on Uno, #13, #12, #11) and the above for CS/DC/RST Adafruit_ILI9341 tft = Adafruit_ILI9341(TFT_CS, TFT_DC, TFT_RST); XPT2046_Touchscreen ts(TS_CS); //Definizione dei prototipi delle funzioni void drawLives(); void drawScore(); void drawLevel(); void initGameBoard(); void clearOldBallPos(); void moveBall(); void moveBat(); void checkHitBat(); void checkHitBlock(); boolean checkAllBlocksHit(); void newBall(); void initGame(); // Global variables float xCalM = 0.0, yCalM = 0.0; float xCalC = 0.0, yCalC = 0.0; float xPos = 0.0, yPos = 0.0; float xPosLast = 0.0, yPosLast = 0.0; float xVel = 0.0, yVel = 0.0; int8_t topBorder = 20; int8_t batWidth = 30; int8_t batHeight = 7; int16_t batX = 0, batY = 0; int8_t ballSize = 3; int playerLives = 3; int playerScore = 0; int gameState = 1; // 1=start 2=playing 3=gameover int level; int16_t tftWidth = 0, tftHeight = 0; class ScreenPoint { public: int16_t x; int16_t y; ScreenPoint(){ // default contructor } ScreenPoint(int16_t xIn, int16_t yIn){ x = xIn; y = yIn; } }; class Block { public: int x; int y; int width; int height; int colour; int score; boolean isActive; // default constructor Block(){} Block(int xpos, int ypos, int bwidth, int bheight, int bcol, int bscore){ x = xpos; y = ypos; width = bwidth; height = bheight; colour = bcol; score = bscore; isActive = true; drawBlock(); } void drawBlock(){ tft.fillRect(x,y,width,height,colour); } void removeBlock(){ tft.fillRect(x,y,width,height,ILI9341_BLACK); isActive = false; } boolean isHit(float x1,float y1, int w1,int h1) { if (checkCollision((int)round(x1),(int)round(y1),w1,h1,x,y,width,height)) { return true; } else { return false; } } }; Block blocks[5][16]; ScreenPoint getScreenCoords(int16_t x, int16_t y){ int16_t xCoord = round((x * xCalM) + xCalC); int16_t yCoord = round((y * yCalM) + yCalC); if(xCoord < 0) xCoord = 0; if(xCoord >= tftWidth) xCoord = tftWidth - 1; if(yCoord < 0) yCoord = 0; if(yCoord >= tftHeight) yCoord = tftHeight - 1; return(ScreenPoint(xCoord, yCoord)); } void calibrateTouchScreen(){ TS_Point p; int16_t x1,y1,x2,y2; Serial.println("Calibrating touch screen..."); Serial.print("Height: ");Serial.print(tftHeight); Serial.print(" x Width: ");Serial.println(tftWidth); Serial.println("Touch the corners as indicated to calibrate the touch screen..."); tft.fillScreen(ILI9341_BLACK); // wait for no touch while(ts.touched()); tft.drawFastHLine(10,20,20,ILI9341_RED); tft.drawFastVLine(20,10,20,ILI9341_RED); while(!ts.touched()); p = ts.getPoint(); x1 = p.x; y1 = p.y; tft.drawFastHLine(10,20,20,ILI9341_BLACK); tft.drawFastVLine(20,10,20,ILI9341_BLACK); delay(500); while(ts.touched()); tft.drawFastHLine(tftWidth - 30,tftHeight - 20,20,ILI9341_RED); tft.drawFastVLine(tftWidth - 20,tftHeight - 30,20,ILI9341_RED); while(!ts.touched()); p = ts.getPoint(); x2 = p.x; y2 = p.y; tft.drawFastHLine(tftWidth - 30,tftHeight - 20,20,ILI9341_BLACK); tft.drawFastVLine(tftWidth - 20,tftHeight - 30,20,ILI9341_BLACK); int16_t xDist = tftWidth - 40; int16_t yDist = tftHeight - 40; // translate in form pos = m x val + c // x xCalM = (float)xDist / (float)(x2 - x1); xCalC = 20.0 - ((float)x1 * xCalM); // y yCalM = (float)yDist / (float)(y2 - y1); yCalC = 20.0 - ((float)y1 * yCalM); Serial.print("x1 = ");Serial.print(x1); Serial.print(", y1 = ");Serial.print(y1); Serial.print(" x2 = ");Serial.print(x2); Serial.print(", y2 = ");Serial.println(y2); Serial.print("xCalM = ");Serial.print(xCalM); Serial.print(", xCalC = ");Serial.print(xCalC); Serial.print(" yCalM = ");Serial.print(yCalM); Serial.print(", yCalC = ");Serial.println(yCalC); Serial.println("Calibration complete!"); } void setup() { Serial.begin(9600); Serial.println(".............................^v^........................."); Serial.println("Game setup()"); // avoid chip select contention pinMode(TS_CS, OUTPUT); digitalWrite(TS_CS, HIGH); pinMode(TFT_CS, OUTPUT); digitalWrite(TFT_CS, HIGH); tft.begin(); tft.setRotation(ROTATION); tft.fillScreen(ILI9341_BLACK); tftWidth = tft.width(); tftHeight = tft.height(); ts.begin(); ts.setRotation(ROTATION); calibrateTouchScreen(); batY = tftHeight - batHeight -30; Serial.println("Setup complete..."); } void initGame(){ tft.fillScreen(ILI9341_BLACK); tft.drawFastHLine(0, topBorder-1, tftWidth, ILI9341_BLUE); tft.setCursor(0,5); tft.setTextSize(1); tft.setTextColor(ILI9341_WHITE); tft.print("SCORE :"); tft.setCursor((tftWidth/2), 5); tft.print("LIVES :"); tft.setCursor(tftWidth - 75, 5); tft.print("LEVEL :"); batY = tftHeight - batHeight -30; playerLives = 3; playerScore = 0; level = 0; drawLives(); drawScore(); drawLevel(); initGameBoard(); } void initGameBoard() { int row, col; int colour, score; clearOldBallPos(); xPosLast = xPos = 0; yPosLast = yPos = 90; xVel = 2; yVel = 2 + (level); gameState = 2; for(row=0; row < 5; row++){ for (col=0; col < 16; col++){ switch(row){ case 0: case 1: colour = ILI9341_BLUE; score = 50; break; case 2: case 3: colour = ILI9341_MAGENTA; score = 30; break; case 4: case 5: colour = ILI9341_YELLOW; score = 10; break; } blocks[row][col] = Block(col*20, (row*10) + 30, 19, 9,colour,score); } } } void clearOldBallPos(){ tft.fillCircle(round(xPosLast), round(yPosLast), ballSize, ILI9341_BLACK); } void moveBall(){ float newX, newY; newX = xPos + xVel; newY = yPos + yVel; if (newX < (float)ballSize){ newX = (float)ballSize; xVel = -xVel; } if (newX > (float)(tftWidth - ballSize - 1)){ newX = (float)(tftWidth - ballSize - 1); xVel = -xVel; } if (newY < topBorder + (float)ballSize){ newY = topBorder + (float)ballSize; yVel = -yVel; } if ((round(newX) != round(xPosLast)) || (round(newY) != round(yPosLast))){ // draw ball clearOldBallPos(); tft.fillCircle(round(newX), round(newY), ballSize, ILI9341_GREEN); xPosLast = newX; yPosLast = newY; } xPos = newX; yPos = newY; } void drawScore(){ // clear old score tft.fillRect(50,5,25,10,ILI9341_BLACK); // print new score tft.setCursor(50,5); tft.setTextSize(1); tft.setTextColor(ILI9341_WHITE); tft.print(playerScore); } void drawLives(){ // clear old lives tft.fillRect((tftWidth/2)+50,5,25,10,ILI9341_BLACK); // print new score tft.setCursor((tftWidth/2)+50,5); tft.setTextSize(1); tft.setTextColor(ILI9341_WHITE); tft.print(playerLives); } void drawLevel(){ // clear old level tft.fillRect(tftWidth-25,5,25,10,ILI9341_BLACK); // print new score tft.setCursor(tftWidth-25,5); tft.setTextSize(1); tft.setTextColor(ILI9341_WHITE); tft.print(level + 1); } void newBall(){ xPos = 0; yPos = 90; xVel = yVel = 2; moveBall(); delay(1000); } boolean checkBallLost(){ if (yPos > tftHeight + ballSize){ return true; } else { return false; } } void moveBat(){ int16_t newBatX; ScreenPoint sp = ScreenPoint(0,0); if (ts.touched()) { TS_Point p = ts.getPoint(); sp = getScreenCoords(p.x, p.y); newBatX = sp.x - (batWidth / 2); if (newBatX < 0) newBatX = 0; if (newBatX >= (tftWidth - batWidth)) newBatX = tftWidth - 1 - batWidth; } if (abs(newBatX - batX) > 4){ tft.fillRect(batX, batY, batWidth, batHeight,ILI9341_BLACK); batX = newBatX; tft.fillRect(batX, batY, batWidth, batHeight,ILI9341_RED); } } // bounding box collision detection boolean checkCollision(int x1, int y1, int width1, int height1, int x2, int y2, int width2, int height2){ boolean hit = false; if ( (((x2 + width2) >= x1) && (x2 <= (x1 + width1))) && (((y2 + height2) >= y1) && (y2 <= (y1 + height1))) ) { hit = true; } return hit; } void checkHitBat(){ // check bat and bottom half of ball float xInc; boolean hit = checkCollision(batX, batY, batWidth, batHeight, (int)round(xPos)-ballSize, (int)round(yPos), ballSize*2, ballSize); if (hit) { // reverse ball y direction but increase speed yVel += 0.05; if (yVel > 5){ yVel = 5; } yVel = -yVel; // rounded bounce xInc = (xPos - (float)(batX + (batWidth / 2))) / (float)batWidth; xVel += 6 * xInc; if (abs(xVel) > 6){ if (xVel < 0) { xVel = -6; } else { xVel = 6; } } // make sure ball not hitting bat yPos = (float)(batY - ballSize -1); } } void checkHitBlock(){ int row, col; for (row=0; row<5; row++){ for (col=0; col<16; col++){ if (blocks[row][col].isActive && blocks[row][col].isHit(xPos,yPos, ballSize*2,ballSize*2)){ blocks[row][col].removeBlock(); playerScore += blocks[row][col].score; drawScore(); yVel = -yVel; return; } } } } boolean checkAllBlocksHit(){ int row, col, actives; actives = 0; for (row=0; row<5; row++){ for (col=0; col<16; col++){ if (blocks[row][col].isActive){ return false; } } } return true; } unsigned long lastFrame = millis(); void loop(void) { Serial.print("GameLoop state: ");Serial.println(gameState); // limit frame rate while((millis() - lastFrame) < 20); lastFrame = millis(); switch(gameState){ case 1: // start gameState = 11; break; case 11: // click to play tft.fillRect((tftWidth/2)-100,(tftHeight/2)-20,200,40,ILI9341_GREEN); tft.setCursor((tftWidth/2)-100+25,(tftHeight/2)-20+12); tft.setTextSize(2); tft.setTextColor(ILI9341_WHITE); tft.print("CLICK TO PLAY"); gameState = 12; break; case 12: // wait for click to play if (ts.touched()) { TS_Point p = ts.getPoint(); ScreenPoint sp = getScreenCoords(p.x, p.y); if (checkCollision(sp.x, sp.y,1,1,(tftWidth/2)-50,(tftHeight/2)-20,100,40)){ initGame(); gameState = 2; } } break; case 2: // play moveBall(); moveBat(); checkHitBat(); checkHitBlock(); if (checkBallLost()){ playerLives --; drawLives(); if (playerLives > 0){ newBall(); } else { gameState = 3; // end game } } if (checkAllBlocksHit()){ gameState = 4; } break; case 4: // new blocks delay(1000); level ++; drawLevel(); initGameBoard(); break; case 3: // end tft.fillScreen(ILI9341_BLACK); tft.setCursor((tftWidth/2)-150,50); tft.setTextSize(3); tft.setTextColor(ILI9341_WHITE); tft.print("You Scored "); tft.print(playerScore); gameState = 11; // click to play break; } }
Calcolatrice
Il seguente è un esempio dell'implementazione di pulsanti sullo schermo.... non è perfetto ma lo scopo non è creare una calcolatrice ma usare dei pulsanti sullo schermo.
Non ci sono modifiche hardware a quanto già fatto, lo sketch seguente è implementato in VS Code con estensione PlatformIO:
#include <Arduino.h> #include "SPI.h" #include "Adafruit_GFX.h" #include "Adafruit_ILI9341.h" #include "XPT2046_Touchscreen.h" #include "Math.h" // Usare #include <ArduinoExprEval.h> // For the Adafruit shield, these are the default. #define TS_CS 7 #define TFT_RST 8 #define TFT_DC 9 #define TFT_CS 10 #define TFT_MOSI 11 #define TFT_MISO 12 #define TFT_CLK 13 #define ROTATION 3 // Landscape //-------------------CLASSI class ScreenPoint { public: int16_t x; int16_t y; ScreenPoint(){ // default contructor } ScreenPoint(int16_t xIn, int16_t yIn){ x = xIn; y = yIn; } }; class MyButton { public: int x; int y; int width; int height; String label; // Constructors MyButton(){} MyButton(int xPos, int yPos, int w, int h, String lab) { x = xPos; y = yPos; width = w; height = h; label = lab; } }; //------------------------- // Use hardware SPI (on Uno, #13, #12, #11) and the above for CS/DC/RST Adafruit_ILI9341 tft = Adafruit_ILI9341(TFT_CS, TFT_DC, TFT_RST); XPT2046_Touchscreen ts(TS_CS); MyButton m_Btns[16]; // Per comodità ci conserviamo i parametri di posizione di ogni bottone //-- (Inizio) Definizione dei prototipi delle funzioni void CalibrateTouchScreen(); ScreenPoint GetScreenCoords(int16_t x, int16_t y); void PrintDisplayArea(String str); void DrawAndSetCalculator(); void DebugPrint_ButtonsInfo(); boolean CheckCollision(int xTouchPoint, int yTouchPoint, int widthTP, int heightTP , int xButton, int yButton, int widthB, int heightB); //-- (Fine) Definizione dei prototipi delle funzioni // Global variables unsigned long lastFrame = millis(); const int c_leftMargin = 20; const int c_rightMargin = 20; const int c_topMargin = 10; int16_t m_tftWidth = 0, m_tftHeight = 0; // Dimensioni schermo TFT // Variabili calibrate per il touch screen: float m_xCalM = 0.0, m_yCalM = 0.0; float m_xCalC = 0.0, m_yCalC = 0.0; String m_stringaDisplay = ""; String m_stringNumber2 = ""; long m_number1 = 0; long m_number2 = 0; String m_CalcState = ""; void CalibrateTouchScreen(){ TS_Point p; int16_t x1,y1,x2,y2; // Coordinate lette dal touch screen in base ai valori dei RESISTORI! Serial.println("Calibrating touch screen..."); Serial.print("Height: ");Serial.print(m_tftHeight); Serial.print(" x Width: ");Serial.println(m_tftWidth); Serial.println("Touch the corners as indicated to calibrate the touch screen..."); tft.fillScreen(ILI9341_BLACK); while(ts.touched()); // In realtà sembra inutile //Disegna un + in alto a SX tft.drawFastHLine(10,20,20,ILI9341_RED); tft.drawFastVLine(20,10,20,ILI9341_RED); //Attende che l'utente tocchi lo schermo per poi prenderne la posizione while(!ts.touched()); // ! p = ts.getPoint(); x1 = p.x; // Valore della resistenza sulle ascisse y1 = p.y; // Valore della resistenza sulle ascisse tft.drawFastHLine(10,20,20,ILI9341_BLACK); // Cancella il + tft.drawFastVLine(20,10,20,ILI9341_BLACK); Serial.println("Touch the corners bottom right on the screen..."); delay(500); while(ts.touched()); // In realtà sembra inutile //Disegna un + in basso a DX tft.drawFastHLine(m_tftWidth - 30,m_tftHeight - 20,20,ILI9341_RED); tft.drawFastVLine(m_tftWidth - 20,m_tftHeight - 30,20,ILI9341_RED); //Attende che l'utente tocchi lo schermo per poi prenderne la posizione while(!ts.touched()); // ! p = ts.getPoint(); x2 = p.x; y2 = p.y; tft.drawFastHLine(m_tftWidth - 30,m_tftHeight - 20,20,ILI9341_BLACK); // Cancella il + tft.drawFastVLine(m_tftWidth - 20,m_tftHeight - 30,20,ILI9341_BLACK); // ********************************************************** // ! Calcola i coefficienti di trasformazione ! // ********************************************************** const int16_t c_BothXMargin = 40; //ex 40 const int16_t c_BothYMargin = 40; //ex 40 const float c_TouchXMargin = 20.0; // Ex 20.0 Margine in pixel da considerare sul touch screen const float c_TouchYMargin = 20.0; // Ex 20.0 Margine in pixel da considerare sul touch screen int16_t xDist = m_tftWidth - c_BothXMargin; int16_t yDist = m_tftHeight - c_BothYMargin; // translate in form pos = m x val + c // x m_xCalM = (float)xDist / (float)(x2 - x1); m_xCalC = c_TouchXMargin - ((float)x1 * m_xCalM); // y m_yCalM = (float)yDist / (float)(y2 - y1); m_yCalC = c_TouchYMargin - ((float)y1 * m_yCalM); Serial.print("(x1 = ");Serial.print(x1); Serial.print(", y1 = ");Serial.print(y1); Serial.print(") - (x2 = ");Serial.print(x2); Serial.print(", y2 = ");Serial.print(y2);Serial.println(")"); Serial.print("m_xCalM = ");Serial.print(m_xCalM); Serial.print(", m_xCalC = ");Serial.print(m_xCalC); Serial.print(" - m_yCalM = ");Serial.print(m_yCalM); Serial.print(", m_yCalC = ");Serial.println(m_yCalC); Serial.println("Calibration complete!"); } // Converte le coordinate lette dal touch screen in coordinate dello schermo TFT ScreenPoint GetScreenCoords(int16_t x, int16_t y){ int16_t xCoord = round((x * m_xCalM) + m_xCalC); int16_t yCoord = round((y * m_yCalM) + m_yCalC); // Correzione se escono dai limiti dello schermo: if(xCoord < 0) xCoord = 0; if(xCoord >= m_tftWidth) xCoord = m_tftWidth - 1; if(yCoord < 0) yCoord = 0; if(yCoord >= m_tftHeight) yCoord = m_tftHeight - 1; return(ScreenPoint(xCoord, yCoord)); } // Stampa l'area di display della calcolatrice void PrintDisplayArea(String str){ tft.fillRect(c_leftMargin,c_topMargin, (m_tftWidth-c_leftMargin-c_rightMargin),24, ILI9341_PURPLE); tft.setCursor(c_leftMargin+5, c_topMargin+5); tft.setTextSize(2); tft.setTextColor(ILI9341_WHITE); tft.print(str); } // Disegna la calcolatrice e setta i bottoni void DrawAndSetCalculator(){ String btnLbl = " "; tft.fillScreen(ILI9341_BLACK); int c_buttonWH = 22; int c_buttonSpacing = 10; // Display dei calcoli: PrintDisplayArea("0"); // Reset display area // 5 Bottoni 0 1 2 3 4 int buttonY = c_topMargin + 24 + 8; // =42 int x = 0; for (int col=0; col<=4; col++){ x = c_leftMargin + (col * (c_buttonWH + c_buttonSpacing)); btnLbl = (String)col; m_Btns[col] = MyButton(x, buttonY, c_buttonWH, c_buttonWH, btnLbl); // x,y , w ,h , color tft.fillRect(x,buttonY, c_buttonWH,c_buttonWH, ILI9341_LIGHTGREY); tft.setCursor(x+5, buttonY+5); tft.setTextSize(2); tft.setTextColor(ILI9341_BLUE); tft.print(col); } // 5 Bottoni 5 6 7 8 9 buttonY += c_buttonWH + c_buttonSpacing; // 42+22+10 =74 for (int col=5; col<=9; col++){ x = c_leftMargin + ((col-5) * (c_buttonWH + c_buttonSpacing)); btnLbl = (String)col; m_Btns[col] = MyButton(x, buttonY, c_buttonWH, c_buttonWH, btnLbl); // x,y , w , h , color tft.fillRect(x,buttonY, c_buttonWH,c_buttonWH, ILI9341_LIGHTGREY); tft.setCursor(x+5, buttonY+5); tft.setTextSize(2); tft.setTextColor(ILI9341_BLUE); tft.print(col); } // 6 Bottoni + - * / = C buttonY += c_buttonWH + c_buttonSpacing; // 74+22+10 =106 for (int col=0; col<=5; col++){ x = c_leftMargin + (col * (c_buttonWH + c_buttonSpacing)); // x,y , w ,h , color tft.fillRect(x,buttonY, c_buttonWH,c_buttonWH, ILI9341_MAROON); tft.setCursor(x+5, buttonY+5); tft.setTextSize(2); tft.setTextColor(ILI9341_WHITE); switch (col) { case 0: btnLbl = "+"; tft.print(btnLbl); break; case 1: btnLbl = "-"; tft.print(btnLbl); break; case 2: btnLbl = "*"; tft.print(btnLbl); break; case 3: btnLbl = "/"; tft.print(btnLbl); break; case 4: btnLbl = "="; tft.print(btnLbl); break; case 5: btnLbl = "C"; tft.print(btnLbl); break; } m_Btns[10+col] = MyButton(x, buttonY, c_buttonWH, c_buttonWH, btnLbl); // Label da settare dopo } } void DebugPrint_ButtonsInfo(){ Serial.println(); Serial.println("Buttons info:"); for (int i=0; i<=15; i++){ Serial.print("Button "); Serial.print(i); Serial.print(" - x: "); Serial.print(m_Btns[i].x); Serial.print(", y: "); Serial.print(m_Btns[i].y); Serial.print(", w: "); Serial.print(m_Btns[i].width); Serial.print(", h: "); Serial.print(m_Btns[i].height); Serial.print(", label: "); Serial.print(m_Btns[i].label); Serial.println("."); } Serial.println(); } boolean CheckCollision(int xTouchPoint, int yTouchPoint, int widthTP, int heightTP , int xButton, int yButton, int widthB, int heightB){ boolean hit = false; if ( (((xButton + widthB) >= xTouchPoint) && (xButton <= (xTouchPoint + widthTP))) && (((yButton + heightB) >= yTouchPoint) && (yButton <= (yTouchPoint + heightTP))) ) { hit = true; } return hit; } // !!!!!!!!!!!!!!!!!!!!!!!!!!!! Arduino setup and loop functions !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! void setup() { Serial.begin(9600); Serial.println("Test Calcolatrice"); // avoid chip select contention pinMode(TS_CS, OUTPUT); digitalWrite(TS_CS, HIGH); pinMode(TFT_CS, OUTPUT); digitalWrite(TFT_CS, HIGH); tft.begin(); tft.setRotation(ROTATION); tft.fillScreen(ILI9341_BLACK); m_tftWidth = tft.width(); m_tftHeight = tft.height(); ts.begin(); ts.setRotation(ROTATION); CalibrateTouchScreen(); DrawAndSetCalculator(); DebugPrint_ButtonsInfo(); } void loop() { // Prosegue solo quando sono passati 20 ms dall'ultimo touch while((millis() - lastFrame) < 40); lastFrame = millis(); if (ts.touched()) { TS_Point p = ts.getPoint(); //delay(200); // debounce while(ts.touched()); // Attende che l'utente rilasci il touch, per evitare di scrivere ripetutamente lo stesso carattere ScreenPoint sp = GetScreenCoords(p.x, p.y); Serial.print("Hit pos. x="); Serial.print(sp.x); Serial.print(", y="); Serial.print(sp.y); Serial.print("."); Serial.print(" ~x="); Serial.print(p.x); Serial.print(", ~y="); Serial.println(p.y); for (int i=0; i<=15; i++){ if (CheckCollision(sp.x , sp.y , 4 , 4, m_Btns[i].x, m_Btns[i].y, m_Btns[i].width, m_Btns[i].height)){ Serial.print("--> Btn i="); Serial.print(i); Serial.print(" - lbl: "); Serial.print(m_Btns[i].label); Serial.println("."); //m_stringaDisplay = m_stringaDisplay.replace("0",""); // Rimuove l'underscore di reset display area switch (i) { case 0: m_stringaDisplay += m_Btns[i].label; // Bottone 0 PrintDisplayArea(m_stringaDisplay); if (m_CalcState == "OpSum" || m_CalcState == "OpSub" || m_CalcState == "OpMul" || m_CalcState == "OpDiv") { m_stringNumber2 += m_Btns[i].label; // Bottone 0 } break; case 1: m_stringaDisplay += m_Btns[i].label; // Bottone 1 PrintDisplayArea(m_stringaDisplay); if (m_CalcState == "OpSum" || m_CalcState == "OpSub" || m_CalcState == "OpMul" || m_CalcState == "OpDiv"){ m_stringNumber2 += m_Btns[i].label; // Bottone 1 } break; case 2: m_stringaDisplay += m_Btns[i].label; // Bottone 2 PrintDisplayArea(m_stringaDisplay); if (m_CalcState == "OpSum" || m_CalcState == "OpSub" || m_CalcState == "OpMul" || m_CalcState == "OpDiv"){ m_stringNumber2 += m_Btns[i].label; // Bottone 2 } break; case 3: m_stringaDisplay += m_Btns[i].label; // Bottone 3 PrintDisplayArea(m_stringaDisplay); if (m_CalcState == "OpSum" || m_CalcState == "OpSub" || m_CalcState == "OpMul" || m_CalcState == "OpDiv"){ m_stringNumber2 += m_Btns[i].label; // Bottone 3 } break; case 4: m_stringaDisplay += m_Btns[i].label; // Bottone 4 PrintDisplayArea(m_stringaDisplay); if (m_CalcState == "OpSum" || m_CalcState == "OpSub" || m_CalcState == "OpMul" || m_CalcState == "OpDiv") { m_stringNumber2 += m_Btns[i].label; // Bottone 4 } break; case 5: m_stringaDisplay += m_Btns[i].label; // Bottone 5 PrintDisplayArea(m_stringaDisplay); if (m_CalcState == "OpSum" || m_CalcState == "OpSub" || m_CalcState == "OpMul" || m_CalcState == "OpDiv") { m_stringNumber2 += m_Btns[i].label; // Bottone 5 } break; case 6: m_stringaDisplay += m_Btns[i].label; // Bottone 6 PrintDisplayArea(m_stringaDisplay); if (m_CalcState == "OpSum" || m_CalcState == "OpSub" || m_CalcState == "OpMul" || m_CalcState == "OpDiv"){ m_stringNumber2 += m_Btns[i].label; // Bottone 6 } break; case 7: m_stringaDisplay += m_Btns[i].label; // Bottone 7 PrintDisplayArea(m_stringaDisplay); if (m_CalcState == "OpSum" || m_CalcState == "OpSub" || m_CalcState == "OpMul" || m_CalcState == "OpDiv"){ m_stringNumber2 += m_Btns[i].label; // Bottone 7 } break; case 8: m_stringaDisplay += m_Btns[i].label; // Bottone 8 PrintDisplayArea(m_stringaDisplay); if (m_CalcState == "OpSum" || m_CalcState == "OpSub" || m_CalcState == "OpMul" || m_CalcState == "OpDiv") { m_stringNumber2 += m_Btns[i].label; // Bottone 8 } break; case 9: m_stringaDisplay += m_Btns[i].label; // Bottone 9 PrintDisplayArea(m_stringaDisplay); if (m_CalcState == "OpSum" || m_CalcState == "OpSub" || m_CalcState == "OpMul" || m_CalcState == "OpDiv"){ m_stringNumber2 += m_Btns[i].label; // Bottone 9 } break; case 10: // Operazione + m_CalcState = "OpSum"; m_number1 = m_stringaDisplay.toInt(); m_stringaDisplay += m_Btns[i].label; // Bottone + PrintDisplayArea(m_stringaDisplay); break; case 11: // Operazione - m_CalcState = "OpSub"; m_number1 = m_stringaDisplay.toInt(); m_stringaDisplay += m_Btns[i].label; // Bottone - PrintDisplayArea(m_stringaDisplay); break; case 12: // Operazione * m_CalcState = "OpMul"; m_number1 = m_stringaDisplay.toInt(); m_stringaDisplay += m_Btns[i].label; // Bottone * PrintDisplayArea(m_stringaDisplay); break; case 13: // Operazione / m_CalcState = "OpDiv"; m_number1 = m_stringaDisplay.toInt(); m_stringaDisplay += m_Btns[i].label; // Bottone / PrintDisplayArea(m_stringaDisplay); break; case 14: { // Operatore = m_stringaDisplay += m_Btns[i].label; // Bottone = m_number2 = m_stringNumber2.toInt(); long result = 0; if (m_CalcState == "OpSum"){ result = m_number1 + m_number2; } else if (m_CalcState == "OpSub"){ result = m_number1 - m_number2; } else if (m_CalcState == "OpMul"){ result = m_number1 * m_number2; } else if (m_CalcState == "OpDiv"){ if (m_number2 != 0){ result = m_number1 / m_number2; } else{ m_stringaDisplay = "Err:div0"; PrintDisplayArea(m_stringaDisplay); break; } } m_stringaDisplay += String(result); PrintDisplayArea(m_stringaDisplay); m_CalcState = ""; m_stringaDisplay = ""; m_stringNumber2 = ""; m_number1 = 0; m_number2 = 0; break; } case (int)15: // Operatore C , pulizia calcoli m_CalcState = ""; m_stringaDisplay = ""; m_stringNumber2 = ""; m_number1 = 0; m_number2 = 0; PrintDisplayArea("0"); // Reset display area break; } } } } }
Sketch utili
Scroll del testo
Copiato da GitHub BodManer
/************************************************************* This sketch implements a simple serial receive terminal program for monitoring serial debug messages from another board. Connect GND to target board GND Connect RX line to TX line of target board Make sure the target and terminal have the same baud rate and serial stettings! The sketch works with the ILI9341 TFT 240x320 display and the called up libraries. The sketch uses the hardware scrolling feature of the display. Modification of this sketch may lead to problems unless the ILI9341 data sheet has been understood! Updated by Bodmer 21/7/16 for TFT_ILI9341 library: https://github.com/Bodmer/TFT_ILI9341 BSD license applies, all text above must be included in any redistribution *************************************************************/ // In most cases characters don't get lost at 9600 baud but // it is a good idea to increase the serial Rx buffer from 64 // to 512 or 1024 bytes especially if higher baud rates are // used (this sketch does not need much RAM). // The method described here works well: // http://www.hobbytronics.co.uk/arduino-serial-buffer-size // #include <TFT_ILI9341.h> // Hardware-specific library #include <SPI.h> TFT_ILI9341 tft = TFT_ILI9341(); // Invoke custom library // The scrolling area must be a integral multiple of TEXT_HEIGHT #define TEXT_HEIGHT 16 // Height of text to be printed and scrolled #define BOT_FIXED_AREA 0 // Number of lines in bottom fixed area (lines counted from bottom of screen) #define TOP_FIXED_AREA 16 // Number of lines in top fixed area (lines counted from top of screen) #define YMAX 320 // Bottom of screen area // The initial y coordinate of the top of the scrolling area uint16_t yStart = TOP_FIXED_AREA; // yArea must be a integral multiple of TEXT_HEIGHT uint16_t yArea = YMAX-TOP_FIXED_AREA-BOT_FIXED_AREA; // The initial y coordinate of the top of the bottom text line uint16_t yDraw = YMAX - BOT_FIXED_AREA - TEXT_HEIGHT; // Keep track of the drawing x coordinate uint16_t xPos = 0; // For the byte we read from the serial port byte data = 0; // A few test variables used during debugging boolean change_colour = 1; boolean selected = 1; // We have to blank the top line each time the display is scrolled, but this takes up to 13 milliseconds // for a full width line, meanwhile the serial buffer may be filling... and overflowing // We can speed up scrolling of short text lines by just blanking the character we drew int blank[19]; // We keep all the strings pixel lengths to optimise the speed of the top line blanking void setup() { // Setup the TFT display tft.init(); tft.setRotation(0); // Must be setRotation(0) for this sketch to work correctly tft.fillScreen(TFT_BLACK); // Setup baud rate and draw top banner Serial.begin(9600); tft.setTextColor(TFT_WHITE, TFT_BLUE); tft.fillRect(0,0,240,16, TFT_BLUE); tft.drawCentreString(" Serial Terminal - 9600 baud ",120,0,2); // Change colour for scrolling zone text tft.setTextColor(TFT_WHITE, TFT_BLACK); // Setup scroll area setupScrollArea(TOP_FIXED_AREA, BOT_FIXED_AREA); // Zero the array for (byte i = 0; i<18; i++) blank[i]=0; } void loop(void) { // These lines change the text colour when the serial buffer is emptied // These are test lines to see if we may be losing characters // Also uncomment the change_colour line below to try them // // if (change_colour){ // change_colour = 0; // if (selected == 1) {tft.setTextColor(TFT_CYAN, TFT_BLACK); selected = 0;} // else {tft.setTextColor(TFT_MAGENTA, TFT_BLACK); selected = 1;} //} while (Serial.available()) { data = Serial.read(); // If it is a CR or we are near end of line then scroll one line if (data == '\r' || xPos>231) { xPos = 0; yDraw = scroll_line(); // It can take 13ms to scroll and blank 16 pixel lines } if (data > 31 && data < 128) { xPos += tft.drawChar(data,xPos,yDraw,2); blank[(18+(yStart-TOP_FIXED_AREA)/TEXT_HEIGHT)%19]=xPos; // Keep a record of line lengths } //change_colour = 1; // Line to indicate buffer is being emptied } } // ############################################################################################## // Call this function to scroll the display one text line // ############################################################################################## int scroll_line() { int yTemp = yStart; // Store the old yStart, this is where we draw the next line // Use the record of line lengths to optimise the rectangle size we need to erase the top line tft.fillRect(0,yStart,blank[(yStart-TOP_FIXED_AREA)/TEXT_HEIGHT],TEXT_HEIGHT, TFT_BLACK); // Change the top of the scroll area yStart+=TEXT_HEIGHT; // The value must wrap around as the screen memory is a circular buffer if (yStart >= YMAX - BOT_FIXED_AREA) yStart = TOP_FIXED_AREA + (yStart - YMAX + BOT_FIXED_AREA); // Now we can scroll the display scrollAddress(yStart); return yTemp; } // ############################################################################################## // Setup a portion of the screen for vertical scrolling // ############################################################################################## // We are using a hardware feature of the display, so we can only scroll in portrait orientation void setupScrollArea(uint16_t tfa, uint16_t bfa) { tft.writecommand(ILI9341_VSCRDEF); // Vertical scroll definition tft.writedata(tfa >> 8); // Top Fixed Area line count tft.writedata(tfa); tft.writedata((YMAX-tfa-bfa)>>8); // Vertical Scrolling Area line count tft.writedata(YMAX-tfa-bfa); tft.writedata(bfa >> 8); // Bottom Fixed Area line count tft.writedata(bfa); } // ############################################################################################## // Setup the vertical scrolling start address pointer // ############################################################################################## void scrollAddress(uint16_t vsp) { tft.writecommand(ILI9341_VSCRSADD); // Vertical scrolling pointer tft.writedata(vsp>>8); tft.writedata(vsp); }
Paginazione del testo di log
Il seguente si presta alla scrittura del testo sul display come una sequenza di righe, come in una applicazione di logging o una chat, è tarato per la dimensione minima del testo ovvero 1, sono previste 30 righe e nel caso nel testo ci sia un riotrno accapo questo verrà considerato nel conteggio del rigo corrente. Quando il testo raggiunge il massimo rigo il display viene pulito e si riscrive sul primo rigo e così via.
#include <Arduino.h> #include "SPI.h" #include "Adafruit_GFX.h" #include "Adafruit_ILI9341.h" //---------------------Costanti per il display TFT--------------------- #define TS_CS 7 // Chip Select pin for the touch screen #define TFT_RST 8 // Reset pin #define TFT_DC 9 // Data/Command pin #define TFT_CS 10 // Slave select o Chip Select (CS) pin #define TFT_MOSI 11 #define TFT_MISO 12 #define TFT_CLK 13 const uint8_t m_rotationLandscapeInv = 3; //Rotazione display landscape const uint8_t m_maxRoxsTxt1 = 30; //Numero massimo di righe di testo con dimensione 1 long m_lastUpdateSmartPhone = 0; int m_intCounter = 0; String m_strCount = ""; String m_strMessage = ""; String m_strTmp = ""; int16_t m_tftWidth = 0, m_tftHeight = 0; //Dimensioni schermo TFT, valorizzate in setup() uint8_t m_currRow = 0; //Riga corrente per stampa testo, supponendo di dimensione 1, quindi max 30 righe (m_maxRoxsTxt1) per evitare di sovrascrivere il testo precedente //Per il display TFT Adafruit_ILI9341 m_tft = Adafruit_ILI9341(TFT_CS, TFT_DC, TFT_RST); //---------------------- PROTOTIPI Funzioni globali ---------------------------- void Println(String text, byte textSize, uint16_t colorText); void PrintTFT(int x, int y, const char* text, byte textSize, uint16_t colorText); void PrintTFT(int x, int y, String text, byte textSize, uint16_t colorText); void PrintTFTln(String text, byte textSize, uint16_t colorText); //---------------------- END PROTOTIPI Funzioni globali ------------------------ void setup() { Serial.begin(9600); // Si deselezionano tutti i dispositivi SPI pinMode(TFT_CS, OUTPUT); // pin 10, Chip Select for TFT display pinMode(7, OUTPUT); // Slave Select for second SPI device il touch screen digitalWrite(TFT_CS, HIGH); // pin 10, Chip Select for TFT display digitalWrite(7, HIGH); // Slave Select for second SPI device il touch screen m_tft.begin(); m_tft.setRotation(m_rotationLandscapeInv); m_tft.fillScreen(ILI9341_BLACK); m_tftWidth = m_tft.width(); m_tftHeight = m_tft.height(); //Si attende che la seriale sia pronta, con un timeout di 2 secondi //altrimenti se se ci fosse l'istruzione while (!Serial) e non si avviasse //il Monitor Seriale l'applicazione andrebbe in loop infinito unsigned long previousMillis = millis(); unsigned long currentMillis = millis(); while (!Serial && (currentMillis - previousMillis <= 2000)) { //timeout 2s per evitare di restare bloccati currentMillis = millis(); } m_strMessage = "fine setup()"; Println(m_strMessage, 1, ILI9341_PURPLE); } void loop() { //Scrive il contatore ogni secondo if (millis() - m_lastUpdateSmartPhone > 1000) { m_lastUpdateSmartPhone = millis(); m_intCounter++; m_strCount = String(m_intCounter); m_strMessage = "Conteggio: " + m_strCount; Println(m_strMessage, 1, ILI9341_GREEN); } } void Println(String text, byte textSize, uint16_t colorText) { PrintTFTln(text, textSize, colorText); if (Serial) { Serial.println(text); } } void PrintTFT(int x, int y, const char* text, byte textSize, uint16_t colorText) { m_tft.setCursor(x, y); m_tft.setTextColor(colorText); m_tft.setTextSize(textSize); m_tft.print(text); } void PrintTFT(int x, int y, String text, byte textSize, uint16_t colorText) { if (x == -1 && y == -1) { m_tft.setCursor(x, y); } m_tft.setTextColor(colorText); m_tft.setTextSize(textSize); m_tft.print(text); } void PrintTFTln(String text, byte textSize, uint16_t colorText) { if (text.indexOf('\n') != -1) { m_currRow++; } m_tft.setTextColor(colorText); m_tft.setTextSize(textSize); m_tft.println(text); m_currRow++; if (m_currRow >= m_maxRoxsTxt1) { m_currRow = 0; m_tft.fillScreen(ILI9341_BLACK); // Pulisce lo schermo quando si raggiunge il numero massimo di righe m_tft.setCursor(0, 0); // Torna alla prima riga dopo aver pulito lo schermo } }
Lettore SSD
Questo particolare display consente persino la lettura di una scheda di memoria SSD!
Il materiale per studiare ed implementare è sul sito Bytes N Bits, attualmente solo un video ma esaustivo. Sarà necessario uno switch di corrente come già visto, allo scopo si suggerisce qui l'uso di "level shifter" (ce ne sono di bidirezionali da 5V a 3.3 e viceversa).
La libreria da utilizzare è quella standard di Arduino "SD Library", il file system supportato è FAT32 (purtroppo i nomi dei files devono essere nel formato corto 8.3 ed i files da referenziare DEVONO essere nella root!), per info arduino.cc.
Riporto l'immagine da Bytes N Bits, il display è sempre lo stesso e la cablatura anche, prestare solo attenzione ai cavi che puntano al lato corto del display in quanto sono quelli per la lettura delle SD. ATTENZIONE non dare corrente con la scheda SD inserita ma spegnere, aggiungere la scheda e poi dare corrente ad Arduino Uno!
ScritturaLettura di un file
#include <Arduino.h> #include "SPI.h" #include "SD.h" #define SD_CLK 13 #define SD_MISO 12 #define SD_MOSI 11 #define SD_CS 6 // Chip Select pin for SD card module int m_maxLoops = 50; void setup() { Serial.begin(115200); pinMode(SD_CS, OUTPUT); digitalWrite(SD_CS, HIGH); if (!SD.begin(SD_CS)) { Serial.println("SD card failed, or not present"); int i = 0; bool lopCondition = i < m_maxLoops; while (lopCondition){ /* code */ i++; delay(200); } return; } else { Serial.println("SD card initialized."); } // Si crea un file File myFile = SD.open("myFile1.txt", FILE_WRITE); if (myFile) { myFile.println("Contenuto di esempio scritto su SD (rigo1)."); myFile.println("Contenuto di esempio scritto su SD (rigo2)."); myFile.close(); Serial.println("File myFile1.txt creato e dato scritto."); } else { Serial.println("Errore nell'apertura del file myFile1.txt"); } // Legge il file appena creato myFile = SD.open("myFile1.txt"); if (myFile) { Serial.println("Contenuto di myFile1.txt:"); while (myFile.available()) { Serial.write(myFile.read()); } myFile.close(); } else { Serial.println("Errore nell'apertura del file myFile1.txt"); } } void loop() { }
Lettura file immagine
- Videotutorial 1 Bytes N Bits
- Tutorial 1 Bytes N Bits
- Tutorial su adafruit-gfx-graphics-library
- Videotutorial 2 Bytes N Bits
- Tutorial 2 Bytes N Bits
#include "SPI.h" #include "Adafruit_GFX.h" // Core graphics library #include "Adafruit_ILI9341.h" // Hardware-specific library #include "SdFat.h" // SD card & FAT filesystem library #include "Adafruit_ImageReader.h" // Image-reading functions #include "XPT2046_Touchscreen.h" #define TFT_CS 10 #define TFT_DC 9 #define TFT_MOSI 11 #define TFT_CLK 13 #define TFT_RST 8 #define TFT_MISO 12 #define TS_CS 7 #define SD_CS 6 // Chip Select pin for SD card module #define ROTATION 3 Adafruit_ILI9341 tft = Adafruit_ILI9341(TFT_CS, TFT_DC, TFT_RST); XPT2046_Touchscreen ts(TS_CS); int tft_width, tft_height; SdFat SD; // SD card filesystem Adafruit_ImageReader reader; // Create an image reader object void setup() { Serial.begin(115200); pinMode(TS_CS, OUTPUT); digitalWrite(TS_CS, HIGH); pinMode(TFT_CS, OUTPUT); digitalWrite(TFT_CS, HIGH); pinMode(SD_CS, OUTPUT); digitalWrite(SD_CS, HIGH); tft.begin(); tft.setRotation(ROTATION); tft_width = tft.width(); tft_height = tft.height(); ts.begin(); ts.setRotation(ROTATION); Serial.println("TFT initialized"); if (!SD.begin(SD_CS)) { Serial.println("SD card initialization failed!"); return; } Serial.println("SD card initialized."); ImageReturnCode stat; stat = reader.drawBMP("test.bmp", tft, 0, 0); // Draw BMP at (0,0) } void loop() { }
Con Arduino Uno R3 - Nano 33 IoT - Nano ESP32
Le due implementazioni a confronto:Nel mio caso, con uno sketch complesso con elaborazione di grafica e testo integrato con funzionalità del touch screen (usando le librerie prima citate) pur conservando esattamente gli stessi riferimenti ai pin, non c'è stato alcun problema, ha compilato al primo colpo.
Il vantaggio con Arduino Nano 33 IoT/ESP32 è quello di lavorare direttamente con una tensione da 3.3V e non usare le resistenze per abbattere la tensione.
NOTE
- su Nano 33 IoT non ho potuto usare il pin 12 chiamato VUSB o +5V poiché contrariamente dalle attese non passa tensione (0V) che invece ho potuto trovare sul pin VIN che è in posizione 15.
- La configurazione per Nano ESP 32 invece usa l'allaccio della tensione a 5V sul pin 12 chiamato VUSB o +5V.
(Mappa e Link)
Arduino indice | Arduino | Integrazioni tipiche | Arduino Progetti | Arduino C++
C++ Info fondamentali | Dizionario Elettronica | Dizionario
Parole chiave:
