[Resolu] ESP32 et Touchscreen

Bonsoir
J'ai réussi à connecter et utiliser un écran TFT 2.4" SPI avec mon ESP32. J'utilise le SPI hardware, selon un tuto trouvé sur le net. J'aimerais ajouter le touch. J'ai connecté les pins comme je l'avais fait avec mon précédent montage sur un nano, reste à choisir la broche CS du touchscreen.
J'ai choisi la 8, mais ça ne marche pas mieux que d'autres essais... Je n'ai pas connecté la broche d'interruption.

Voici mon code : il semble que même quand je ne touche pas l'écran, le touch s'active et me donne des coordonnées nulles en x et y. Même chose si je touche l'écran un peu partout.

#include "SPI.h"
#include "Adafruit_GFX.h"
#include "Adafruit_ILI9341.h"

#define _cs   17  // goes to TFT CS
#define _dc   16  // goes to TFT DC
#define _mosi 23  // goes to TFT MOSI
#define _sclk 18  // goes to TFT SCK/CLK
#define _rst  5   // goes to TFT RESET
#define _miso     // Not connected
//       3.3V     // Goes to TFT LED
//       5v       // Goes to TFT Vcc
//       Gnd      // Goes to TFT Gnd

// Use hardware SPI
Adafruit_ILI9341 tft = Adafruit_ILI9341(_cs, _dc, _rst);

// If using software SPI change pins as desired
//Adafruit_ILI9341 tft = Adafruit_ILI9341(_cs, _dc, _mosi, _sclk, _rst);

// Touch
#include <XPT2046_Touchscreen.h> // Touch
#define CS_PIN   8
//#define TIRQ_PIN 2
XPT2046_Touchscreen ts(CS_PIN);
//XPT2046_Touchscreen ts(CS_PIN, TIRQ_PIN);  // Param 2 - Touch IRQ Pin - interrupt enabled polling

#include <Fonts/FreeSans12pt7b.h>  // include fancy sans-serif font

// Paramètres
uint16_t couleur = 1;
float echelle = 0.1;
int angle = 0;
int pas_angle = 2;
int num_courbe = 2;
int x;
int y;
int xprev;
int yprev;
float theta;
boolean wastouched = true;

void setup() {
  Serial.begin(115200);

  tft.begin();
  tft.setRotation(3);

  // Init touchscreen
  ts.begin();
  while (!Serial && (millis() <= 1000));
  init_affichage ();
}

void loop()
{
  affiche_point ();
  boolean istouched = ts.touched();
  if (istouched) {
    TS_Point p = ts.getPoint();
//    if (!wastouched) {
      int x_touch = p.x;
      int y_touch = p.y;
      Serial.print(x_touch); Serial.print("\t"); Serial.println(y_touch);
      if (x_touch < 41)
      {
        num_courbe = y_touch / 40 + 1;
        angle = 0;
        echelle = 0.1;
        init_affichage();
      }
//    }
  }
  wastouched = istouched;
}

void courbe (int& xi, int& yi, float t, float a, int n) {
  float xc;
  float yc;
  switch (n) {
    case 1:
      xc = cos(2 * t) + sin(3 * t);
      yc = sin(2 * t) + cos(t);
      break;
    case 2:
      xc = cos(4 * t) - sin(2 * t);
      yc = sin(3 * t) + cos(t) * cos(t);
      break;
    case 3:
      xc = cos(t) + sin(2 * t);
      yc = sin(5 * t) + cos(2 * t);
      break;
    case 4:
      xc = 1.5 * cos(t) / 1.13;
      yc = 1.5 * sin(t);
      break;
    case 5:
      xc = sin(t) + cos(t);
      yc = sin(2 * t) + cos(2 * t);
      break;
    case 6:
      xc = sin(3 * t) + cos(3 * t);
      yc = sin(2 * t) + cos(2 * t);
      break;
  }
  xi = map (a * xc * 100, -200, 200, 50, 320);
  yi = map (a * yc * 100, -200, 200, 0, 240);
}

void init_affichage()
{
  tft.fillScreen(ILI9341_WHITE);
  tft.fillRect (0,   0, 40, 40, ILI9341_BLUE);
  tft.fillRect (0,  40, 40, 40, ILI9341_RED);
  tft.fillRect (0,  80, 40, 40, ILI9341_GREEN);
  tft.fillRect (0, 120, 40, 40, ILI9341_YELLOW);
  tft.fillRect (0, 160, 40, 40, ILI9341_MAGENTA);
  tft.fillRect (0, 200, 40, 40, ILI9341_CYAN);
  tft.setFont(&FreeSans12pt7b);
  tft.setTextColor (ILI9341_BLACK);
  tft.setTextSize (1);
  for (int i = 1; i < 7; i++) {
    char num = 48;
    tft.setCursor(13, (i - 1) * 40 + 27);
    num += i;
    tft.print(num);
  }
  tft.setCursor(125, 18);
  tft.print(F("COURBE "));
  tft.print(num_courbe);
  courbe (xprev, yprev, 0, echelle, num_courbe);
}

void affiche_point () {
  angle += pas_angle;
  if (angle > 360)
  {
    angle = 0;
    echelle += 0.05;
    couleur = couleur + 1000;
    if (echelle > 1)
    {
      echelle = 0.05;
    }
    courbe (xprev, yprev, 0, echelle, num_courbe);
  }
  theta = angle * PI / 180;
  courbe (x, y, theta, echelle, num_courbe);
  tft.drawLine (xprev, yprev, x, y, couleur);
  xprev = x;
  yprev = y;
}

Quelqu'un a une idée ?

Il y a déjà eu dans le passé des problèmes de ce genre là qui sont remontés.
Il faut s'assurer que dans les librairies utilisés le CS est bien remis à 1, à la fin des transactions SPI. Sinon tu te retrouves avec 2 périphériques sur le bus en même temps.
Le plus simple dans un premier temps étant de manipuler le CS par toi même ce qui confirmera ou pas le problème. C'est un peu laborieux à ajouter mais si après ça tu n'as plus de problème tu pourras aller investiguer dans les librairies pour traiter le problème à sa source.
Exemple sur le setup()

void setup() {
  Serial.begin(115200);

  tft.begin();
  tft.setRotation(3);
  digitalWtrite(_cs, HIGH);
  // Init touchscreen
  ts.begin();
  digitalWtrite(CS_PIN, HIGH);
  while (!Serial && (millis() <= 1000));
  init_affichage ();
  digitalWtrite(_cs, HIGH);
}

Au passage, des noms de signaux plus explicites clarifieraient le code.
CS_TFT, CS_TOUCH par exemple

Bonjour
GPIO 8est peut être occupé pour gérére la mémoire flash SPI comme c'est le cas sur ce 'pinmap'
gpio8.png

@al1fch : tu suggères d'utiliser une autre broche pour le CS ? La 4 par exemple ?

@fdufnews : si je comprends bien, à la fin des affichages je mets le _cs (que je renommerai promis :slight_smile: ) à HIGH, et à la fin de la lecture du touch je mets le CS_PIN à HIGH ? Ceci aussi bien dans le setup que dans la loop. Correct ?

J'essaye tout ça ce soir... Merci

Faut-il que j'utilise l'interruption (interrupt enabled polling) ?

lesept:
@fdufnews : si je comprends bien, à la fin des affichages je mets le _cs (que je renommerai promis :slight_smile: ) à HIGH, et à la fin de la lecture du touch je mets le CS_PIN à HIGH ? Ceci aussi bien dans le setup que dans la loop. Correct ?

Exactement

Ça donne ça (je mets juste le setup et la loop, le reste ne change pas) :

#include "SPI.h"
#include "Adafruit_GFX.h"
#include "Adafruit_ILI9341.h"

#define TFT_cs   17  // goes to TFT CS             // <-- changement de noms
#define TFT_dc   16  // goes to TFT DC
#define TFT_mosi 23  // goes to TFT MOSI
#define TFT_sclk 18  // goes to TFT SCK/CLK
#define TFT_rst  5   // goes to TFT RESET
#define TFT_miso     // Not connected
//       3.3V     // Goes to TFT LED
//       5v       // Goes to TFT Vcc
//       Gnd      // Goes to TFT Gnd

// Use hardware SPI
Adafruit_ILI9341 tft = Adafruit_ILI9341(TFT_cs, TFT_dc, TFT_rst);

// If using software SPI change pins as desired
//Adafruit_ILI9341 tft = Adafruit_ILI9341(TFT_cs, TFT_dc, TFT_mosi, TFT_sclk, TFT_rst);

// Touch
#include <XPT2046_Touchscreen.h> // Touch
#define TOUCH_CS   4                                     // <-- changement de nom
//#define TOUCH_TIRQ 2
XPT2046_Touchscreen ts(TOUCH_CS);
//XPT2046_Touchscreen ts(TOUCH_CS, TOUCH_TIRQ);  // Param 2 - Touch IRQ Pin - interrupt enabled polling

#include <Fonts/FreeSans12pt7b.h>  // include fancy sans-serif font

// Paramètres
uint16_t couleur = 1;
float echelle = 0.1;
int angle = 0;
int pas_angle = 2;
int num_courbe = 2;
int x;
int y;
int xprev;
int yprev;
float theta;
boolean wastouched = true;

void setup() {
  Serial.begin(115200);

  tft.begin();
  tft.setRotation(3);
  digitalWrite(TFT_cs, HIGH);                   // <-- là
  // Init touchscreen
  ts.begin();
  digitalWrite(TOUCH_CS, HIGH);             // <-- là
  
  while (!Serial && (millis() <= 1000));
  init_affichage ();
}

void loop()
{
  affiche_point ();
  digitalWrite(TFT_cs, HIGH);                   // <-- là
  boolean istouched = ts.touched();
  if (istouched) {
    TS_Point p = ts.getPoint();
//    if (!wastouched) {
      int x_touch = p.x;
      int y_touch = p.y;
      Serial.print(x_touch); Serial.print("\t"); Serial.println(y_touch);
      if (x_touch < 41)
      {
        num_courbe = y_touch / 40 + 1;
        angle = 0;
        echelle = 0.1;
        init_affichage();
      }
//    }
  }
  digitalWrite(TOUCH_CS, HIGH);               // <-- là
  wastouched = istouched;  
}

Correct ?

Oui

Merci !

@al1fch : tu suggères d'utiliser une autre broche pour le CS ? La 4 par exemple ?

tester une autre broche , oui
GPIO4 ? pas en priorité vu qu'il semble doté d'un 'pull down'(pd), je testerai plutôt l'un des GPIO les plus 'banalisés' ....au besoin aller taper dans la rangée GPIO 27 à GPIO36

ceci dit il me semble que l'usage efficace du SPI sur ESP32 necessiterait d'étudier le fonctionnement des 2 ports SPI hardware disponibles(HSPI et VSPI) sur les 4 dont est doté l'ESP32... chose que je n'ai pas faite.
L'exemple "SPI_Multiple buses" montre l'usage de HSPI et VSPI

N.B : il y a encore beaucoup de débroussaillage à faire pour exploiter l'ESP32 de manière étendue !! en attendant que ceci soit fait puis vulgarisé il faut accepter de tâtonner.....

Bon, j'ai essayé avec le code modifié et les pins 4, 34, 36 : toujours pareil...

Un example içi (ILI9341 + XPT2046) pour ESP32

C'est 'pour info' et non testé, je n'utilise pas ces écrans

lesept:
il semble que même quand je ne touche pas l'écran, le touch s'active et me donne des coordonnées nulles en x et y. Même chose si je touche l'écran un peu partout.

Il ne faut pas exclure non plus un écran tactile défectueux.
Tu as regardé à l'ohmmètre ce qu'il y a entre les broches de l'écran tactile?

Merci Alain, je vais tester
A priori, il fonctionne (le display marche avec l'ESP32, le touch fonctionnait sur un nano, mais je n'ai pas testé depuis quelques temps)

Une question sur le code trouvé par Alain :

#define _mosi              32 /* 10K pull-up */
...
#define TFT_CS              4 /* 10K pull-up */
...
#define TFT_BACKLIGHT_PIN   2 /* -via transistor- */
#define TOUCH_CS_PIN       33 /* 10K pull-up */

"10k pull-up" signifie que je dois connecter une résistance entre la pin de l'écran et le 3.3V ?

mosi ---- broche 32 de l'ESP32
mosi ---- R 10 kohms ---- 3.3V

Et le "via transistor" ? Pour moi ça marche de brancher directement le backlight sur le 3.3V, je laisse comme ça ?

Bon j'ai essayé sans les pullup resistors, mais ça ne fonctionne pas mieux : toujours x = 0 et y = 0.
J'ai retesté l'écran sur le nano, il fonctionne parfaitement, le touch aussi.

1 Like

Bon finalement, après avoir posé ma question dans la partie Display du forum, j'ai réussi à le faire fonctionner.

J'utilise la bibli TFT_eSPI qui est compatible Adafruit et permet de gérer le touch via XPT2046_Touchscreen. Elle est facile d'utilisation et avec le hardware SPI ça dépote !!!

Il faut déclarer les pins dans un fichier de setup : voici ce que j'ai choisi

// For ESP32 Dev board (only tested with ILI9341 display)
// The hardware SPI can be mapped to any pins

#define TFT_MISO 19
#define TFT_MOSI 23
#define TFT_SCLK 18
#define TFT_CS    5  // Chip select control pin (15)
#define TFT_DC    2  // Data Command control pin
#define TFT_RST   4  // Reset pin (could connect to RST pin)

et

#define SPI_FREQUENCY  40000000 // Maximum to use SPIFFS

// The XPT2046 requires a lower SPI clock rate of 2.5MHz so we define that here:
#define SPI_TOUCH_FREQUENCY  2500000