Skip to Content

Premiers pas avec Matouch 1.28″ ToolSet_Controller

Premiers pas avec Matouch 1.28″ ToolSet_Controller

Le Matouch 1.28″ ToolSet_Controller est une carte de développement compacte ESP32-S3 avec de nombreuses fonctionnalités. Elle est équipée d’un écran tactile RGB rond de 1,28 pouce avec une bague encodeur rotatif, Wi-Fi, Bluetooth 5.0, et un retour haptique par vibration. On trouve également un RTC, un emplacement pour carte micro-SD, ainsi que des connecteurs pour I²C, UART, SPI et GPIO.

Dans ce guide de démarrage, vous apprendrez comment configurer la carte pour la programmation avec l’Arduino IDE. Deux exemples de code vous montreront comment utiliser l’écran, l’écran tactile, l’encodeur rotatif et le moteur pour le retour haptique.

Commençons …

Pièces requises

Vous aurez besoin d’une carte Matouch 1.28″ ToolSet_Controller de Makerfabset d’un câble USB-C pour programmer la carte et tester les exemples de code.

Matouch 1.28″ ToolSet_Controller

Câble USB-C

Makerguides is a participant in affiliate advertising programs designed to provide a means for sites to earn advertising fees by linking to Amazon, AliExpress, Elecrow, and other sites. As an Affiliate we may earn from qualifying purchases.

Le Matouch 1.28″ ToolSet_Controller

Le Matouch 1.28″ ToolSet_Controller est propulsé par le microcontrôleur ESP32-S3, qui offre un traitement dual-core ainsi que la connectivité Wi-Fi et Bluetooth 5.0. Au centre se trouve un écran IPS RGB rond de 1,28 pouce avec une résolution de 240 × 240 pixels. L’écran supporte le tactile capacitif pour une interaction précise. Autour de l’écran, une bague encodeur rotatif avec bouton-poussoir intégré permet une saisie intuitive comme le défilement, le réglage du volume ou la navigation dans les menus.

Front  of Matouch 1.28" ToolSet_Controller
Face avant du Matouch 1.28″ ToolSet_Controller

Composants du Matouch 1.28″ ToolSet_Controller

En plus de l’écran et du contrôle rotatif, la carte intègre un moteur de vibration haptique qui fournit un retour tactile. Une horloge temps réel (RTC) assure une mesure précise du temps même en mode deep sleep. Pour le stockage local, l’emplacement micro-SD facilite la journalisation des données ou le stockage de médias.

Back of Matouch 1.28" ToolSet_Controller
Dos du Matouch 1.28″ ToolSet_Controller

La carte mesure 60 × 60 millimètres. Ce design carré et compact facilite son intégration dans des contrôleurs portables, des outils de bureau et des interfaces utilisateur. L’extension est possible via des connecteurs accessibles pour I²C, UART, SPI et GPIO, permettant l’utilisation de capteurs externes, d’actionneurs ou d’autres modules. L’alimentation est gérée par un système embarqué supportant à la fois USB Type-C et batterie externe, mais sans circuit de charge.

Brochage du Matouch 1.28″ ToolSet_Controller

L’image ci-dessous montre le brochage du Matouch 1.28″ ToolSet_Controller. Il y a 15 broches GPIO ainsi que des broches d’alimentation 5V ou 3,3V disponibles :

Pinout of Matouch 1.28" ToolSet_Controller
Brochage du Matouch 1.28″ ToolSet_Controller

Le Matouch 1.28″ ToolSet_Controller est idéal pour des projets nécessitant une interface compacte mais performante. Parmi les applications possibles : un contrôleur média de bureau pour ajuster le volume ou changer de piste, un panneau de contrôle domotique ou un outil de configuration de périphériques.

Spécifications techniques

Le tableau ci-dessous résume les spécifications techniques de la carte.

SpécificationDétails
MicrocontrôleurESP32-S3 dual-core, Xtensa LX7
Sans filWi-Fi 802.11 b/g/n, Bluetooth 5.0
ÉcranIPS RGB rond 1,28″, 240 × 240 pixels, tactile capacitif
Entrée rotativeBague encodeur rotatif avec bouton-poussoir
VibrationMoteur haptique
StockageEmplacement micro-SD
HorlogeHorloge temps réel (RTC)
ExtensionI²C, UART, SPI, GPIO
AlimentationUSB Type-C, batterie externe
Dimensions60 × 60 mm
Support open-sourceArduino IDE, projets exemples sur GitHub

Enfin, vous pouvez trouver le schéma électrique du Matouch 1.28″ ToolSet_Controller via le lien suivant :

Installation du Core ESP32

Si c’est votre premier projet avec une carte de la série ESP32, vous devrez d’abord installer le core ESP32. Si les cartes ESP32 sont déjà installées dans votre Arduino IDE, vous pouvez passer cette section.

Commencez par ouvrir la boîte de dialogue Préférences en sélectionnant “Preferences…” dans le menu “File”. Cela ouvrira la fenêtre de préférences ci-dessous.

Sous l’onglet Settings, vous trouverez un champ de saisie en bas de la fenêtre intitulé “Additional boards manager URLs” :

Additional boards manager URLs in Preferences
URLs supplémentaires du gestionnaire de cartes dans les Préférences

Dans ce champ, copiez l’URL suivante :

https://espressif.github.io/arduino-esp32/package_esp32_dev_index.json

Cela permettra à l’Arduino IDE de savoir où trouver les bibliothèques du core ESP32. Ensuite, nous installerons les cartes ESP32 via le Boards Manager.

Ouvrez le Boards Manager via « Tools -> Boards -> Board Manager ». Le gestionnaire de cartes apparaîtra dans la barre latérale gauche. Tapez « ESP32 » dans le champ de recherche en haut et vous verrez deux types de cartes ESP32 : les « Arduino ESP32 Boards » et les « esp32 par Espressif ». Nous voulons les « esp32 libraries par Espressif ». Cliquez sur le bouton INSTALL et attendez la fin du téléchargement et de l’installation.

Install ESP32 Core libraries
Installer les bibliothèques Core ESP32

Sélection de la carte

Enfin, il faut sélectionner une carte ESP32. Pour le Matouch 1.28″ ToolSet_Controller, choisissez le module générique « ESP32S3 Dev Module ». Pour cela, cliquez sur le menu déroulant puis sur « Select other board and port… »:

Drop-down Menu for Board Selection
Menu déroulant pour la sélection de la carte

Cela ouvrira une fenêtre où vous pourrez taper « esp32s3 dev » dans la barre de recherche. Vous verrez la carte « ESP32S3 Dev Module » dans la liste. Cliquez dessus, sélectionnez le port COM, puis cliquez sur OK :

Board Selection Dialog "ESP32S3 Dev Module" board
Dialogue de sélection de carte « ESP32S3 Dev Module »

Notez que vous devez connecter la carte via le câble USB à votre ordinateur avant de pouvoir sélectionner un port COM.

Installer la bibliothèque Adafruit GFX

Une fois le code ESP32 installé, l’étape suivante est d’installer la Arduino_GFX bibliothèque par moononournation, qui sera utilisée pour dessiner sur l’écran Matouch 1.28″. Ouvrez le LIBRARY MANAGER, tapez « GFX Library for Arduino » dans la barre de recherche, trouvez la « GFX Library for Arduino » par Moon, et cliquez sur INSTALL :

Installation of GFX Library for Arduino
Installation de la bibliothèque GFX pour Arduino via LIBRARY MANAGER

Tout est maintenant prêt pour écrire et exécuter du code sur le Matouch 1.28″ ToolSet_Controller.

Code pour l’encodeur, le moteur et l’écran

Dans ce premier sketch, vous apprendrez à utiliser l’écran, l’encodeur et le moteur pour le retour haptique.

Nous utiliserons la bague de l’encodeur pour modifier la luminosité de l’écran entre 1 % et 100 % et afficherons la valeur de luminosité à l’écran. Une courte vibration signalera si la bague est tournée trop loin (<1 %, >100 %). Enfin, appuyer sur le bouton-poussoir de l’encodeur activera ou désactivera l’écran. La photo ci-dessous montre l’écran éteint, à 4 % de luminosité et à 100 % de luminosité :

Jetez d’abord un coup d’œil rapide au code complet, puis nous en discuterons les détails :

#include <Arduino_GFX_Library.h>

#define TFT_BLK 45
#define TFT_RES 21
#define TFT_CS 1
#define TFT_MOSI 2
#define TFT_MISO -1
#define TFT_SCLK 42
#define TFT_DC 46

#define ENCODER_BTN 17
#define ENCODER_CLK 48
#define ENCODER_DT 47

#define MOTOR_PIN 41

int brightness = 50;
bool btn_display = true;
int enc_state = 0;
int old_state = -1;
bool has_changed = true;

Arduino_ESP32SPI *bus = new Arduino_ESP32SPI(TFT_DC, TFT_CS, TFT_SCLK,
                                             TFT_MOSI, TFT_MISO, HSPI, true);
Arduino_GFX *gfx = new Arduino_GC9A01(bus, TFT_RES, 0 /* rotation */, true /* IPS */);

void encoder_irq() {
  enc_state = digitalRead(ENCODER_CLK);
  if (enc_state != old_state) {
    brightness = digitalRead(ENCODER_DT) == enc_state ? brightness + 1 : brightness - 1;
  }
  old_state = enc_state;
  has_changed = true;
}

void button_irq() {
  btn_display = !btn_display;
  has_changed = true;
}

void draw_text() {
  gfx->setTextSize(2);
  gfx->setCursor(60, 55);
  gfx->println(F("Makerguides"));
}

void limit_brightness() {
  if (brightness > 100 || brightness < 0) {
    digitalWrite(MOTOR_PIN, HIGH);
    delay(50);
    digitalWrite(MOTOR_PIN, LOW);
  }
  brightness = constrain(brightness, 0, 100);
}

void update_brightness() {
  gfx->fillRect(65, 95, 120, 65, WHITE);
  gfx->setTextSize(6);
  gfx->setCursor(65, 100);
  gfx->printf("%3d", brightness);

  int b = map(brightness, 0, 100, 1, 255);
  analogWrite(TFT_BLK, btn_display ? b : 0);
}

void init_display() {
  gfx->begin();
  gfx->fillScreen(WHITE);
  gfx->setTextColor(BLACK);
}

void init_pins() {
  pinMode(TFT_BLK, OUTPUT);
  digitalWrite(TFT_BLK, HIGH);

  pinMode(MOTOR_PIN, OUTPUT);

  pinMode(ENCODER_BTN, INPUT);
  pinMode(ENCODER_CLK, INPUT);
  pinMode(ENCODER_DT, INPUT);

  attachInterrupt(ENCODER_CLK, encoder_irq, CHANGE);
  attachInterrupt(ENCODER_BTN, button_irq, FALLING);
}

void setup(void) {
  Serial.begin(115200);
  init_pins();
  init_display();
  draw_text();
}

void loop() {
  if (has_changed) {
    has_changed = false;
    limit_brightness();
    update_brightness();
  }
}

Imports

Le programme commence par inclure la bibliothèque graphique pour l’écran rond GC9A01. Ce fichier d’en-tête apporte les pilotes d’écran, les constantes de couleur telles que WHITE, BLACK, ou RED, ainsi que les primitives de dessin.

#include <Arduino_GFX_Library.h>

Constantes de broches et matériel

Des constantes nommées associent des étiquettes significatives aux broches GPIO de l’ESP32. Elles définissent la broche PWM du rétroéclairage TFT, la réinitialisation, la sélection de puce, les broches SPI, les données/commande de l’écran, le bouton-poussoir de l’encodeur rotatif et ses deux canaux quadrature, ainsi que la broche de contrôle du moteur de vibration. Les définir ici rend le reste du code plus lisible.

#define TFT_BLK 45
#define TFT_RES 21
#define TFT_CS 1
#define TFT_MOSI 2
#define TFT_MISO -1
#define TFT_SCLK 42
#define TFT_DC 46

#define ENCODER_BTN 17
#define ENCODER_CLK 48
#define ENCODER_DT 47

#define MOTOR_PIN 41

Variables d’état globales

Quelques variables globales conservent la luminosité actuelle, l’état marche/arrêt de l’écran, le dernier niveau logique de l’encodeur et sa valeur précédente, ainsi qu’un drapeau “dirty” indiquant au loop principal qu’un changement est survenu suite à une interruption. La luminosité initiale est de 50 %, l’écran est activé au démarrage, et old_state est initialisé à une valeur impossible (-1) pour que la première lecture de l’encodeur soit considérée comme un changement.

int brightness = 50;
bool btn_display = true;
int enc_state = 0;
int old_state = -1;
bool has_changed = true;

Objets bus d’affichage et pilote

Deux objets configurent l’écran. Arduino_ESP32SPI configure le bus SPI et les broches de contrôle du TFT. Le constructeur sélectionne les broches DC, CS, SCLK, MOSI et MISO, choisit le périphérique HSPI et active le DMA pour des transferts plus rapides. Arduino_GC9A01 est le pilote spécifique pour le panneau rond 1,28″ ; il reçoit l’objet bus SPI, la broche reset, la rotation et le flag IPS. L’objet résultant gfx expose les méthodes de dessin utilisées dans tout le sketch.

Arduino_ESP32SPI *bus = new Arduino_ESP32SPI(TFT_DC, TFT_CS, TFT_SCLK,
                                             TFT_MOSI, TFT_MISO, HSPI, true);
Arduino_GFX *gfx = new Arduino_GC9A01(bus, TFT_RES, 0 /* rotation */, true /* IPS */);

Routine d’interruption : encoder_irq

Cette ISR s’exécute à chaque changement de la ligne CLK de l’encodeur. Elle lit le niveau actuel de CLK et le compare au précédent. Si une transition est détectée, elle regarde la ligne DT pour déterminer la direction : quand DT est égal au nouveau niveau CLK, la luminosité augmente, sinon elle diminue. Elle mémorise ensuite le nouvel état et marque l’interface utilisateur comme modifiée pour que la boucle principale redessine et applique la nouvelle luminosité. Utiliser une ISR rend l’encodeur réactif sans attendre activement dans loop().

void encoder_irq() {
  enc_state = digitalRead(ENCODER_CLK);
  if (enc_state != old_state) {
    brightness = digitalRead(ENCODER_DT) == enc_state ? brightness + 1 : brightness - 1;
  }
  old_state = enc_state;
  has_changed = true;
}

Routine d’interruption : button_irq

Cette ISR bascule l’état marche/arrêt de l’écran. Chaque front descendant sur le bouton-poussoir de l’encodeur inverse btn_display et signale qu’un changement est survenu pour que la boucle principale mette à jour l’écran et le rétroéclairage.

void button_irq() {
  btn_display = !btn_display;
  has_changed = true;
}

Assistant de dessin : draw_text

Cet assistant place un label fixe “Makerguides” près du haut de l’écran rond. Il définit une petite taille de texte, déplace le curseur et affiche la chaîne depuis la mémoire flash (F() macro).

void draw_text() {
  gfx->setTextSize(2);
  gfx->setCursor(60, 55);
  gfx->println(F("Makerguides"));
}

Assistant logique : limit_brightness

Cette fonction applique la plage valide de luminosité et signale haptique quand l’utilisateur tente de dépasser cette plage. Si la valeur est hors de [0, 100], elle active brièvement le moteur de vibration pour indiquer la limite, puis contraint la valeur dans la plage avec constrain. Le retour moteur ne se déclenche que lors d’une condition hors plage, donc les butées “vibrent” mais les pas normaux ne le font pas.

void limit_brightness() {
  if (brightness > 100 || brightness < 0) {
    digitalWrite(MOTOR_PIN, HIGH);
    delay(50);
    digitalWrite(MOTOR_PIN, LOW);
  }
  brightness = constrain(brightness, 0, 100);
}

Mise à jour de l’interface et du rétroéclairage : update_brightness

Cette fonction rafraîchit l’affichage numérique à l’écran et applique le nouveau niveau PWM du rétroéclairage. Elle peint d’abord un rectangle blanc sur le nombre précédent pour l’effacer proprement, définit une taille de texte plus grande, positionne le curseur et affiche la luminosité comme une valeur à trois chiffres alignée à droite. Elle convertit ensuite 0–100 % en plage PWM 1–255 et écrit ce cycle de service sur la broche du rétroéclairage. Si l’écran a été éteint via le bouton-poussoir, elle force le cycle à zéro pour éteindre le rétroéclairage sans modifier la valeur de luminosité stockée.

void update_brightness() {
  gfx->fillRect(65, 95, 120, 65, WHITE);
  gfx->setTextSize(6);
  gfx->setCursor(65, 100);
  gfx->printf("%3d", brightness);

  int b = map(brightness, 0, 100, 1, 255);
  analogWrite(TFT_BLK, btn_display ? b : 0);
}

Initialisation de l’écran : init_display

Au démarrage, le pilote d’écran est initialisé, l’écran est effacé en blanc, et la couleur de texte par défaut est mise en noir. Ces étapes garantissent un état de dessin connu avant de rendre les éléments de l’interface.

void init_display() {
  gfx->begin();
  gfx->fillScreen(WHITE);
  gfx->setTextColor(BLACK);
}

Initialisation des broches et câblage des interruptions : init_pins

Tous les modes GPIO sont configurés ici. La broche du rétroéclairage est définie en sortie et mise à l’état haut initialement pour que le panneau soit visible au démarrage. La broche du moteur est en sortie. Les broches bouton-poussoir, CLK et DT de l’encodeur sont en entrée. Notez que l’encodeur possède des résistances pull-up internes de 10K, donc INPUT_PULLUP n’est pas nécessaire ici (même si présent dans certains exemples).

Schematics for pushbutton and encoder
Schéma du bouton-poussoir et de l’encodeur (source)

Enfin, les interruptions matérielles sont attachées : le CLK de l’encodeur utilise CHANGE pour capter les fronts montant et descendant pour une résolution maximale, tandis que le bouton utilise FALLING pour déclencher une fois par pression. Cette configuration garde la boucle principale simple et réactive.

void init_pins() {
  pinMode(TFT_BLK, OUTPUT);
  digitalWrite(TFT_BLK, HIGH);

  pinMode(MOTOR_PIN, OUTPUT);

  pinMode(ENCODER_BTN, INPUT);
  pinMode(ENCODER_CLK, INPUT);
  pinMode(ENCODER_DT, INPUT);

  attachInterrupt(ENCODER_CLK, encoder_irq, CHANGE);
  attachInterrupt(ENCODER_BTN, button_irq, FALLING);
}

Setup

La fonction setup() initialise la liaison série pour le débogage, configure les broches et interruptions, prépare l’écran et dessine le label statique. Après setup(), l’appareil est prêt à réagir aux mouvements de l’encodeur et aux pressions sur le bouton.

void setup(void) {
  Serial.begin(115200);
  init_pins();
  init_display();
  draw_text();
}

Boucle principale

La loop() est volontairement minimale. Elle ne réagit que lorsqu’une ISR a marqué has_changed. Quand ce drapeau est levé, elle le réinitialise, applique les limites de luminosité avec retour haptique si nécessaire, et met à jour le nombre à l’écran ainsi que le PWM du rétroéclairage. Ce schéma évite les redessins et écritures PWM inutiles, ce qui rend l’interface fluide et économe en énergie.

void loop() {
  if (has_changed) {
    has_changed = false;
    limit_brightness();
    update_brightness();
  }
}

Comment l’encodeur contrôle la luminosité et le retour haptique

L’encodeur fournit deux signaux carrés, CLK et DT, dont la phase relative indique la direction. À chaque transition CLK, l’ISR compare DT au nouveau niveau CLK pour décider d’ajouter ou de soustraire un à brightness. Quand l’utilisateur dépasse les limites, limit_brightness() fait vibrer le moteur pendant 50 millisecondes et contraint la valeur dans [0, 100]. La valeur numérique affichée reflète toujours la valeur contrainte, tandis que la luminosité visible vient du PWM sur TFT_BLK, réglé sur le cycle mappé ou à zéro si le bouton-poussoir a éteint l’écran.

Code pour l’écran tactile

Dans cet exemple de code suivant, vous apprendrez à utiliser l’écran tactile. Nous afficherons le texte « Touch » au centre de l’écran et dessinerons un cercle noir à l’endroit touché. La photo ci-dessous montre l’écran du contrôleur avant et après quelques touches :

Comme précédemment, je vous suggère de jeter un coup d’œil rapide au code complet avant d’en discuter les détails :

#include <Wire.h>
#include <Arduino_GFX_Library.h>

#define TFT_BLK 45
#define TFT_RES 21
#define TFT_CS 1
#define TFT_MOSI 2
#define TFT_MISO -1
#define TFT_SCLK 42
#define TFT_DC 46

#define TOUCH_INT 40
#define TOUCH_SDA 38
#define TOUCH_SCL 39
#define TOUCH_RST 18

#define MOTOR_PIN 41

Arduino_ESP32SPI *bus = new Arduino_ESP32SPI(TFT_DC, TFT_CS, TFT_SCLK,
                                             TFT_MOSI, TFT_MISO, HSPI, true);
Arduino_GFX *gfx = new Arduino_GC9A01(bus, TFT_RES, 0 /* rotation */, true /* IPS */);

int read_touch(int *x, int *y) {
  byte data_raw[7];
  i2c_read(0x15, 0x02, data_raw, 7);
  int event = data_raw[1] >> 6;
  if (event == 2) {
    *x = (int)data_raw[2] + (int)(data_raw[1] & 0x0f) * 256;
    *y = (int)data_raw[4] + (int)(data_raw[3] & 0x0f) * 256;
    return 1;
  } 
  return 0;  
}

int i2c_read(uint16_t addr, uint8_t reg_addr, uint8_t *reg_data, uint32_t length) {
  Wire.beginTransmission(addr);
  Wire.write(reg_addr);
  if (Wire.endTransmission(true))
    return -1;
  Wire.requestFrom(addr, length, true);
  for (int i = 0; i < length; i++) {
    *reg_data++ = Wire.read();
  }
  return 0;
}

void init_pins() {
  pinMode(TFT_BLK, OUTPUT);
  digitalWrite(TFT_BLK, HIGH);

  Wire.begin(TOUCH_SDA, TOUCH_SCL);
  pinMode(MOTOR_PIN, OUTPUT);
}

void init_display() {
  gfx->begin();
  gfx->fillScreen(WHITE);
  gfx->setTextColor(BLACK);  
  gfx->setTextSize(3);
  gfx->setCursor(80, 105);
  gfx->print(F("Touch"));
}

void setup(void) {
  Serial.begin(115200);
  init_pins();
  init_display();
}

void loop() {
  static int x, y;
  if (read_touch(&x, &y) == 1) {
    gfx->fillCircle(x, y, 5, BLACK);
    digitalWrite(MOTOR_PIN, HIGH);
    delay(20);
    digitalWrite(MOTOR_PIN, LOW);
  }
}

Imports

Le programme inclut la bibliothèque I²C pour communiquer avec le contrôleur tactile et la même bibliothèque graphique que précédemment pour dessiner sur l’écran circulaire GC9A01. La bibliothèque Wire fournit begin, beginTransmission, write, endTransmission, et requestFrom pour l’accès registre I²C bas niveau, tandis que Arduino_GFX_Library.h apporte le pilote d’écran, les primitives de dessin et les constantes de couleur déjà utilisées.

#include <Wire.h>
#include <Arduino_GFX_Library.h>

Constantes de broches et matériel

Les broches d’écran sont les mêmes que dans le sketch précédent et identifient le rétroéclairage, la réinitialisation, la sélection de puce SPI et les lignes du bus, ainsi que la broche D/C. Des constantes supplémentaires définissent l’interruption, SDA, SCL et la réinitialisation du contrôleur tactile. La broche moteur pilote à nouveau le moteur de vibration haptique. Dans ce sketch, les lignes d’interruption et de reset tactile sont définies pour complétude, mais seules les lignes I²C sont réellement utilisées.

#define TFT_BLK 45
#define TFT_RES 21
#define TFT_CS 1
#define TFT_MOSI 2
#define TFT_MISO -1
#define TFT_SCLK 42
#define TFT_DC 46

#define TOUCH_INT 40
#define TOUCH_SDA 38
#define TOUCH_SCL 39
#define TOUCH_RST 18

#define MOTOR_PIN 41

Objets bus d’affichage et pilote

La configuration de l’écran suit le même schéma qu’avant. Un objet Arduino_ESP32SPI connecte le périphérique HSPI de l’ESP32 avec les broches choisies et DMA activé, et un objet Arduino_GC9A01 pilote le panneau IPS rond de 1,28″. L’objet résultant gfx expose la même API de dessin que vous avez déjà utilisée.

Arduino_ESP32SPI *bus = new Arduino_ESP32SPI(TFT_DC, TFT_CS, TFT_SCLK,
                                             TFT_MOSI, TFT_MISO, HSPI, true);
Arduino_GFX *gfx = new Arduino_GC9A01(bus, TFT_RES, 0 /* rotation */, true /* IPS */);

Lecteur tactile : read_touch

Cette fonction interroge le contrôleur tactile via I²C, analyse un paquet et renvoie les coordonnées du toucher via des pointeurs. Elle lit d’abord sept octets à partir du registre 0x02 de l’adresse 0x15. Le contrôleur encode un “événement” dans les deux bits supérieurs de l’octet X-high ; un décalage de six bits donne ce code d’événement.

Seul l’événement égal à 2 est traité comme un contact valide et les coordonnées sont calculées. La position X est formée en prenant l’octet bas et en ajoutant les quatre bits bas de l’octet haut multipliés par 256, reconstituant une coordonnée 12 bits typique ; Y est décodé de la même façon à partir de ses octets haut et bas.

Quand un toucher valide est décodé, la fonction stocke x et y via les pointeurs et retourne 1. Pour tout autre événement, elle retourne 0.

int read_touch(int *x, int *y) {
  byte data_raw[7];
  i2c_read(0x15, 0x02, data_raw, 7);
  int event = data_raw[1] >> 6;
  if (event == 2) {
    *x = (int)data_raw[2] + (int)(data_raw[1] & 0x0f) * 256;
    *y = (int)data_raw[4] + (int)(data_raw[3] & 0x0f) * 256;
    return 1;
  } 
  return 0;  
}

Assistant I²C : i2c_read

Cet assistant effectue une transaction courante “écrire registre, puis lire données”. Il commence une transmission vers l’adresse 7 bits, écrit l’adresse du registre, et vérifie endTransmission. Un résultat non nul signale une erreur et retourne -1. Il demande ensuite le nombre d’octets spécifié et les récupère de Wire.read() dans le buffer de l’appelant, retournant enfin 0 pour succès. C’est la pièce bas niveau sur laquelle read_touch s’appuie pour récupérer le paquet tactile.

int i2c_read(uint16_t addr, uint8_t reg_addr, uint8_t *reg_data, uint32_t length) {
  Wire.beginTransmission(addr);
  Wire.write(reg_addr);
  if (Wire.endTransmission(true))
    return -1;
  Wire.requestFrom(addr, length, true);
  for (int i = 0; i < length; i++) {
    *reg_data++ = Wire.read();
  }
  return 0;
}

Initialisation des broches et du bus : init_pins

La configuration GPIO reflète le sketch précédent pour le rétroéclairage et le moteur. La broche du rétroéclairage est mise en sortie et activée pour que l’écran soit visible immédiatement. La broche moteur est configurée en sortie prête pour les impulsions haptiques. Le bus I²C est démarré sur les broches SDA et SCL spécifiées avec Wire.begin(TOUCH_SDA, TOUCH_SCL), qui sélectionne les broches alternatives ESP32 définies pour le contrôleur tactile. Aucune interruption tactile n’est attachée ici ; ce sketch choisit un simple sondage.

void init_pins() {
  pinMode(TFT_BLK, OUTPUT);
  digitalWrite(TFT_BLK, HIGH);

  Wire.begin(TOUCH_SDA, TOUCH_SCL);
  pinMode(MOTOR_PIN, OUTPUT);
}

Initialisation de l’écran : init_display

La mise en route de l’écran suit les mêmes étapes que précédemment. Le pilote gfx est lancé, l’écran est effacé en blanc, et la couleur de texte est mise en noir. Un label “Touch” amical est affiché au centre avec une taille de texte plus grande pour indiquer l’interaction attendue. Le macro F() conserve la chaîne en mémoire flash.

void init_display() {
  gfx->begin();
  gfx->fillScreen(WHITE);
  gfx->setTextColor(BLACK);  
  gfx->setTextSize(3);
  gfx->setCursor(80, 105);
  gfx->print(F("Touch"));
}

Setup

Le démarrage est similaire en structure au sketch précédent. Le port série est ouvert pour le débogage, les broches et le bus I²C sont initialisés, et l’écran est préparé et étiqueté. Après setup, l’appareil est prêt à sonder les touches et afficher le retour.

void setup(void) {
  Serial.begin(115200);
  init_pins();
  init_display();
}

Boucle

La boucle principale interroge continuellement le contrôleur tactile et réagit immédiatement lorsqu’un contact valide est signalé. Les variables x et y sont déclarées static pour que leur stockage persiste entre les itérations, permettant à read_touch d’écrire via les pointeurs.

Quand read_touch retourne 1, un cercle noir rempli de rayon cinq pixels est dessiné aux coordonnées signalées pour marquer la touche. Une courte impulsion de 20 millisecondes active puis désactive le moteur de vibration pour fournir une confirmation haptique du toucher.

void loop() {
  static int x, y;
  if (read_touch(&x, &y) == 1) {
    gfx->fillCircle(x, y, 5, BLACK);
    digitalWrite(MOTOR_PIN, HIGH);
    delay(20);
    digitalWrite(MOTOR_PIN, LOW);
  }
}

Lien avec le sketch précédent

La création, l’initialisation, l’API de dessin de l’écran et le contrôle moteur suivent exactement les mêmes schémas que vous avez déjà utilisés. Au lieu des interruptions encodeur et du drapeau has_changed, ce sketch interroge le contrôleur tactile via I²C et déclenche le retour haptique à chaque contact valide, plutôt qu’aux butées de luminosité.

Le rétroéclairage est simplement activé sans modulation PWM, car il n’y a pas d’état de luminosité ici. Les broches d’interruption et de reset tactile sont définies mais non utilisées ; ajouter une interruption externe sur TOUCH_INT pourrait permettre de dormir entre les touches, tandis que TOUCH_RST pourrait effectuer une réinitialisation matérielle du contrôleur tactile si nécessaire.

Conclusions

Dans ce tutoriel, vous avez appris à démarrer avec le Matouch 1.28″ ToolSet_Controller. Les deux exemples de code autour de l’écran, de l’écran tactile, de l’encodeur rotatif et du retour haptique devraient vous aider à lancer plus facilement votre propre projet.

Nous n’avons pas abordé le Wi-Fi, le Bluetooth 5.0, la carte SD ou le support RTC dans ce tutoriel. Mais vous pouvez trouver des exemples sur Makerfabs’s Github repo for the Matouch display. Si vous souhaitez en savoir plus sur les encodeurs rotatifs, consultez notre tutoriel How To Interface A Quadrature Rotary Encoder.

La base carrée du Matouch 1.28″ ToolSet_Controller peut être un peu grande pour certaines applications. Si vous cherchez un écran similaire avec un encodeur rotatif mais une base ronde, jetez un œil au CrowPanel 1.28inch-HMI ESP32 Rotary Display. Et si vous avez seulement besoin d’un écran rond (sans bague encodeur), le tutoriel Digital Clock on CrowPanel 1.28″ Round Display pourrait vous être utile.

Sinon, n’hésitez pas à poser vos questions dans la section commentaires.

Bon bricolage 😉