Ver 15/03/2026 Scheda Arduino Zero (SAMD21) Display TFT 1024x600 con controller RA8876 Touch capacitivo FT5206 su I2C (Wire), interrupt pin TouchInt=38 Scrivi programmi non bloccanti a stati. Privilegia luso di switch e case. ===== STRUTTURA BASE ===== #include "gevino_tft_io.h" // Respect this sequence #include "All_76_Pic_65K.h" // Rispetta questa sequenza #include "gevino_tft_display.h" // Touch #include FT5206 cts = FT5206(TouchInt); uint8_t registers[FT5206_REGISTERS]; uint16_t coordinates[5][2]; uint8_t current_touches = 0; // touch capacitivo void setup() { SerialUSB.begin(115200); Serial.begin(115200); // ESP Wi-Fi Serial1.begin(115200); // RS485 Serial2.begin(38400); // BT HC-06-07-08 + RS232 Serial3.begin(57600); // GSM SIM800L gevino_io_setup(); if( tft.init() ) SerialUSB.println("RAIO controller OK"); else SerialUSB.println("RAIO controller FAIL"); tft.PWM0(1, 1, 200, 1024, 512); // backlight 50% tft.selectInternalFont(RA8876_FONT_SIZE_32); tft.setTextColor(WHITE, BLACK); cts.begin(INTRL); } void loop() { updateIO(); analogPolling(); (Se si usa analogica) } ===== IO ===== Non inizializzare gli IO, lo fa gia gevino_io_setup(); Ingressi diretti: In0 (pin18/A4), In1 (pin19/A5), In2 (pin8), In3 (pin9) - attivi LOW, la macro inverte Ingressi shift register: In4..In11 (via 74HC165, aggiornati da updateIO()) Uscite: Out0 diretto (pin44), Out1..Out7 via shift register 74HC595 Comandi: setOut0; resOut0; Out0 (lettura stato) ... fino a Out7 Led frontale: setLed; resLed; IMPORTANTE: dopo setOutX/resOutX (tranne Out0) chiamare updateIO() per trasferire allo shift register. ===== API GRAFICA RA8876 - COORDINATE ASSOLUTE ===== ATTENZIONE: drawRect, fillRect, drawLine, drawTriangle, fillTriangle usano COORDINATE ASSOLUTE (x1,y1,x2,y2), NON (x,y,larghezza,altezza). tft.fillRect(x1, y1, x2, y2, color); // riempie rettangolo da (x1,y1) a (x2,y2) tft.drawRect(x1, y1, x2, y2, color); // cornice rettangolo da (x1,y1) a (x2,y2) tft.drawLine(x1, y1, x2, y2, color); // linea da (x1,y1) a (x2,y2) tft.drawTriangle(x1,y1, x2,y2, x3,y3, color); tft.fillTriangle(x1,y1, x2,y2, x3,y3, color); tft.drawCircle(cx, cy, radius, color); // centro + raggio tft.fillCircle(cx, cy, radius, color); // centro + raggio tft.clearScreen(color); tft.drawPixel(x, y, color); Esempio corretto per rettangolo in posizione (x,y) con dimensioni (w,h): tft.fillRect(x, y, x+w-1, y+h-1, color); NON esiste drawFastVLine ne drawFastHLine. Usa drawLine: tft.drawLine(x, y1, x, y2, color); // linea verticale tft.drawLine(x1, y, x2, y, color); // linea orizzontale ===== COLORI ===== Costanti: BLACK, WHITE, BLUE, RED, GREEN, CYAN, MAGENTA, YELLOW, BRIGHT_RED, LIGHT_GREY, DARK_GREY Macro: RGB565(r, g, b) con r,g,b 0-255 ===== TESTO ===== tft.setCursor(x, y); tft.setTextColor(color); // testo con sfondo trasparente (cancella bg) tft.setTextColor(color, bgColor); // testo con sfondo colorato tft.setTextScale(scale); // scala uniforme 1,2,3,4 tft.setTextScale(xScale, yScale); // scala separata tft.print("testo"); // eredita da Print tft.println("testo"); Font interni (ROM RA8876): tft.selectInternalFont(RA8876_FONT_SIZE_16); // 8x16 tft.selectInternalFont(RA8876_FONT_SIZE_24); // 12x24 tft.selectInternalFont(RA8876_FONT_SIZE_32); // 16x32 Font esterni (chip ROM): tft.selectExternalFont(RA8876_FONT_FAMILY_ARIAL, RA8876_FONT_SIZE_24, RA8876_FONT_ENCODING_8859_1); Famiglie: FIXED, ARIAL, TIMES, FIXED_BOLD Font custom GEVA (da flash, definiti in fontExt.h): tft.setFont(¬oSans_20pt); // dimensioni: 8,12,20,32,48,64,80,96,112 pt // Famiglie: notoSans, notoSansBold, notoSansItal, notoSansMono, notoSansMonoBold, notoSerif, notoSerifBold tft.getTextBounds("testo", x, y, &x1, &y1, &w, &h); // calcola dimensioni testo ===== TOUCH FT5206 ===== #include FT5206 cts = FT5206(TouchInt); // TouchInt = pin 38 Setup: cts.begin(INTRL); // oppure SAFE o EXTRLN Polling nel loop (non bloccante): if (cts.touched()) { cts.getTSregisters(touch_reg); uint8_t n = cts.getTScoordinates(touch_coord, touch_reg); // n = numero di tocchi (1-5) // touch_coord[0][0] = X primo tocco // touch_coord[0][1] = Y primo tocco uint8_t gesture = cts.getGesture(touch_reg); // 0=none,1=up,2=left,3=down,4=right,5=zoomIn,6=zoomOut uint8_t flag = cts.getTSflag(touch_reg); // 1=finger up, 2=finger down } Pulsante touch software (pattern): #define BTN_X 100 #define BTN_Y 200 #define BTN_W 150 #define BTN_H 60 if (touch_coord[0][0] >= BTN_X && touch_coord[0][0] <= BTN_X+BTN_W && touch_coord[0][1] >= BTN_Y && touch_coord[0][1] <= BTN_Y+BTN_H) { // pulsante premuto } ===== BACKLIGHT PWM ===== tft.PWM0(on_off, Clock_Divided, Prescalar, Count_Buffer, Compare_Buffer); // on_off: 1=enable, 0=disable // Clock_Divided: 0=1, 1=1/2, 2=1/4, 3=1/8 // Prescalar: 1-256 // Count_Buffer: periodo PWM // Compare_Buffer: duty cycle (tempo alto) Esempio 50%: tft.PWM0(1, 1, 200, 1024, 512); ===== IMMAGINI DA FLASH ===== #include "All_76_Pic_65K.h" // definisce BINARY_INFO[] pic(indice, x, y); // immagine intera pic_part(indice, x, y, sx, sy, w, h); // porzione immagine ===== TIMER NON BLOCCANTE ===== #include "Timer.h" Timer t1(5000); // timer 5 secondi t1.reset(); // riavvia il timer t1.stato(); // true se scaduto t1.fronte(); // true solo al primo fronte di scadenza t1.tempo(3000); // cambia tempo e riavvia ===== RS485 ===== La porta Serial1 รจ usata per la RS485 Half Duplex: set_Rs485_TxEn; Serial1.write(data); // Attendere fine trasmissione: if (SERCOM0->USART.INTFLAG.bit.TXC) { res_Rs485_TxEn; SERCOM0->USART.INTFLAG.bit.TXC = 1; } Per modbus RTU su RS485: ArduinoModbus con ArduinoRS485.h (versione modificata GEVA). ===== SERIALI ===== SerialUSB -> debug USB Serial -> BT SPP-C o WiFi ESP8266 (AT) Serial1 -> RS485 Half-Duplex Serial2 -> BT/RS232 (pin 10,11 SERCOM1) Serial3 -> GSM SIM800L (pin 3,4 SERCOM2) ===== EEPROM ===== FlashStorage per emulare EEPROM su flash interna. ===== ETHERNET ===== W5500, libreria Ethernet standard. Inizializzare con Ethernet.init(ETH_CS); ETH_CS definito in gevino_tft_io.h (pin 5). Per modbus TCP: ArduinoModbus. ===== SD ===== SdFat di Greiman. SD_CS = 12. Inizializzare: sd.begin(SD_CS, SD_SCK_MHZ(12)) ===== ANALOGICI ===== Setup non bloccante: analogPrescaler(ADC_PRESCALER_DIV32); analogReadExtended(10); analogGain(ADC_GAIN_1); analogReference2(ADC_REF_INT1V); analogCalibrate(); analogEnable(); Polling: analogPolling(); // valori in analogResult[0..4] DAC su A0: analogWrite(A0, valore); // 10 bit (0-1023) ===== REGOLE HTML (per web server su W5500) ===== Struttura dei file 1. Separazione modulare: html_content.h, css_content.h, js_content.h, json_handler.h, html_server.h 2. Autenticazione in session_manager.h, traduzioni in translation.h 3. Usare GET per login: /login?pwd=xxx 4. Password letta da configurazione, mai hardcoded 5. Template HTML con R"rawliteral(...)" e placeholder {{nome}} 6. Router HTTP con gestione separata per percorso 7. Traduzioni con array di struct, rilevare lingua browser 8. Log su SerialUSB in punti strategici 9. Timeout sessioni 30min, richieste HTTP 15s max 10. Minimizzare JS, preferire HTML/CSS puro, no framework esterni