Tutoriel menu de différentes pages sur un écran TFT avec la librairie utft

Salut a tous !

Une question revient souvent sur le forum à savoir comment faire un système de plusieurs pages ou menu, sur un écran tactile.
Pré requis :

  • Un shield interface pour l’écran (cas standard)
  • Une carte Arduino
  • L’ide Arduino 1.x
  • Quelque notion de code C/C++
  • Télécharger et installer la librairie UTFT et Utouch
  • UTFT - Rinky-Dink Electronics
  • UTouch - Rinky-Dink Electronics
  • Avoir un écran tactile compatible avec ces librairies
  • Avoir regardé la dattasheet fournie avec les librairies

Variable globale :

Ce qu'il nous faut dans un premier temps, c'est une variable globale au sketch, qui serra ce que j'appellerai un « sélecteur de page ».
Je choisi personnellement de l'appeler :

unsigned int selecteurPage=0;//variable de sélection de menu pour l'interface tactile

Je le déclare volontairement sous forme d’un « unsigned int » pour limiter l’impacte sur l'espace mémoire, je n'ai pas pris un « byte » car la méthode du sélecteur de pages repose sur des multiplications par 10 par sous menus. Vous comprendrez pourquoi plus tard ne soyer pas impatient.
Création des Pages :
Maintenant nous devons crée différentes fonctions qui seront en fait les différentes pages de notre système de menu
Ex :

void Menu_index(){} ;
void Menu_1(){} ;
void Menu_11(){} ;
void Menu_12(){} ;
void Menu_121(){} ;
void Menu_2(){} ;

Bref voici différente « page » ou « fonction page » dont on pourrait représenter l'arborescence ainsi :

Construction du Menu :

Maintenant que nous avons notre variable « sélecteur de page » et nos « fonctions page », on va crée un système pour que nos pages soit sélectionnées en fonction de la valeur du sélecteur. Pour cela tout va ce passer dans la boucle « loop() » à l'intérieur d'un « Switch » :

void loop(){
switch(selecteurPage){
    case 0:
      Menu_Affichage_Principale();
      break;
    case 1:
Menu_1() ;
      break;
    case 11:
Menu_11() ;
      break;
    case 12:
Menu_12() ;
      break;
    case 121:
Menu_121() ;
      break;
    case 2:
Menu_2() ;
      break;
default :
      Menu_Affichage_Principale();
      break;
}}

Que va-t-il ce passer dans notre programme :

Et bien a chaque boucle le système va tester la valeur de notre « sélecteur de page » et effectuer la « fonction page » correspondant au cas sélectionné ! Il affichera donc pour chaque cas la « fonction page » correspondante et donc sont contenu.

Détection de l’appui sur une zone :

Ce qu'il nous faut maintenant, c'est une fonction qui détecte l’appui sur une zone précise. La je me suis servi des données trouvées sur le site http://www.mon-club-elec.fr/
Voici la fonction c'est cadeau :

boolean TestTouche( int zoneX, int zoneY,int Longueur,int hauteur)
{
   int X, Y,testX,testY; // varriable 
  if (myTouch.dataAvailable())// dataAvailable() est une fonction de la lib Utouch.h
    {
        myTouch.read();// read() est une fonction de la lib Utouch.h
        X=myTouch.getX(), Y=myTouch.getY();// getX et getY() sont des fonction de la lib Utouch.h
        //---- vérifie si appui sur la touche "+" ---------
        testX=abs(X-(zoneX+Longueur/2)); // calcul valeur absolue de l'écart de X touchpad à la  Zone X centre touche
        testY=abs(Y-(zoneY+hauteur/2)); // calcul valeur absolue de l'écart de Y touchpad à la  Zone Y centre touche
        if (testX<Longueur/2 && testY<hauteur/2)
         {return true;}
        else
         { return false;}
    }
    return false;
}

Maintenant que nous pouvons détecter l’appui sur une zone on peut alors modifier notre « sélecteur de pages ».

Modification du « sélecteur de pages » :

On va prendre l'exemple de la page d'accueil en imaginant que l'on a créé une interface avec une ou deux zones tactiles.

void Menu_Affichage_Principale(){ 
// Ici on trace affiche ce que l'on veut
// On test s'il y a appuis sur al zone situer au pixel 100,100 //de longueur 50pixel et de hauteur 30pixel
    if (TestTouche( 100, 100,50,30)== true ){
selecteurPage=1;// on sélectionne la nouvelle page à afficher
      return;// on sort de la fonction s’il y’a eu appui
    }
// On test s'il y a appuis sur al zone situer au pixel 200,200 //de longueur 50pixel et de hauteur 30pixel
    if (TestTouche( 200, 200,50,30)== true ){
selecteurPage=2;// on sélectionne la nouvelle page à afficher
      return;// on sort de la fonction s’il y’a eu appui
    }
  return ;
}

Gagner du temps de travail et éviter de réafficher :

Notre système est déjà opérationnel en l’état, mais il n’est pas optimiser car il va sans cesse réafficher l’intégralité de nos pages.
En effet pour ceux qui ont déjà essayé lorsque l'on utilise un écran de grande taille (perso des 5") le temps d'affichage peut être très long et qui dit affichage long dit perte de temps pour faire autre chose!
Voici une astuce pour éviter cela et ainsi gagner du temps d'affichage!
On va donc réfléchir et ce demander à chaque pages crées, qu'est ce qui doit être rafraichie à chaque cycle et qu'est ce qui fait partie du décor (statique)! En gros nos variables de mesures, sondes, accelero ..., elles doivent être réaffichées en permanence.
Par contre les titres, les images, les textes... font partie des choses à ne pas réafficher ! L’idée est donc très simple, on va créer une autre variable globale par exemple comme ça:

boolean  comptAff= false;// compteur d'affichage permet de ne pas rafraichir en permanence

Puis dans notre page d'exemple, on va à nouveau utiliser un Switch qui va tester notre variable "comptAff"

void Menu_Affichage_Principale(){ 
switch(comptAff){
case 0:
// Ici on trace, affiche, ce que l'on veut:
/// Exemple les zone de nos touches
lcd.setBackColor(COLOR_RED);
lcd.drawRect( 100,  100,  50, 30);
lcd.setBackColor(COLOR_GREEN);
lcd.drawRect( 200,  200,  50, 30);
comptAff=true;// on passe la variable d'affichage a vrai pour qu'au prochain cycle cette partie du code ne soit pas réécrite
break;
case 1:
// Ici on affichera no variable :
// Exemple l'heure
    lcd.setFont(small);
    lcd.setColor(COLOR_BLACK);
    lcd.setBackColor(COLOR_WHITE);
     sprintf(Buff_20,"heure:%2i:%02i:%2i",Time.h,Time.m,Time.s);
    lcd.print(Buff_20,30, 30);
// On test s'il y a appuis sur la zone situer au pixel 100,100 //de longueur 50pixel et de hauteur 30pixel
    if (TestTouche( 100, 100,50,30)== true ){
selecteurPage=1;// on sélectionne la nouvelle page a aficher
comptAff=false;// on oublie pas de réinitialiser notre variable d'affichage 
      return;
    }
// on test s'il y a appuis sur la zone situer au pixel 200,200 //de longueur 50pixel et de hauteur 30pixel
    if (TestTouche( 200, 200,50,30)== true ){
selecteurPage=2;// on sélectionne la nouvelle page a afficher
comptAff=false;
      return;
    }
break;
}
  return;
}

Dans le déroulement de notre code on va au premier passage afficher, tout ce qui est statique et ignorer ce qui est dynamique. Au second et tous les autres passages on ignorera la partie statique et on affichera que la partie dynamique, jusqu’au moment ou une action sur une touche de changement de page réinitialise la variable « comptAff ».

Conclusion :

Voila, regardez bien le déroulement du code et vous comprendrez en lisant les commentaires. Les variable et exemple sont des « EXEMPLE » le code n'est pas tester à vous de coder en fonction de votre besoin.
enfin certain vont ce demander pourquoi cette histoire de multiple de 10 pour les menus et bien c'est simple vous voulez créer un bouton retour, vous n'avez alors qu'a diviser par 10 la variable « sélecteur de page » et hop vous retournez en arrière d'un niveau!

selecteurPage=selecteurPage/10;

Version .doc : [Tutoriel_ menu_tactile.doc](http://christophe.boulic.free.fr/arduino/Tutoriel_ menu_tactile.doc)

Merci, beau travail.
:wink:

Merci si ça peut faire avancé certaint c'est tant mieux :grin:

Cela me rappelle vaguement un truc ^^

ba suite à ton poste il y'a eu des demandes similare sur le forum donc autant tout reprendre et faire un truc propre! :grin:

Salut Heloderma-kris,

Merci pour le tuto. :wink:

Il ya encore peu, j' aurais bien eu besoin de ce tuto, les débutants vont pouvoir s' en donner à cœur joie !!

Ouep la cela va beaucoup aider, j'espère que les prochains à utiliser ce code vont bien comprendre comment cela fonctionne ^^ et pas copier bêtement le code :wink:
La stasifaction de chercher et trouver cest top. Meme quand on se fait un peu aider pour les trucs blocan :slight_smile:

faudra que les personne face l'effort de venir regarder , et c'est la que le bas blèsse!
je me suis commander un LCD 16x4 , si je peut je proposerai un tuto dessu sur cette base car c'est transposable!
merci a vous deux!

Salut les screensplayers, ou re!

oui, très bonne idée pour le 16*4, ce sera même plus accessible pour les débutants sans la partie tactile.
à force de vous lire tous les deux, je vais finir par craquer pour un tactile avec SD!! :grin:
(bon le 3.5 est à 40 boules à Rennes, faut que je trouve une un pote qu' a une CB pour commander "online".)

j' en profite pour poser deux questions sur les Nextion:
quelle différence entre indiegogo, early Bird, Lucky Dog?
Sont-ils plus performant que les autres?

Sinon, je comprends l' intérêt de l' environnement de développement!

Prend sur amazon :wink:
Rapide à venir et correct en tarif. Que cela soit le 3,2 le 5 ou le 7.
Perso j'ai prix que des saint smart car cela fonctionne bien... Mais il ne faut pas alimenter l'arduino en plus de 5v sinon cela crame l'écran :confused:

Salut la team arduino !
Merci pour le tuto, super intéressant !
J'ai une petite question : est ce qu'il existe des boîtiers en plastique adaptés aux ecrans ?
J'ai automatisé les volets battants de ma maison et j'aimerai ajouter une interface de gestion pour la petite famille à travers un écran tactile. C'est pas très esthétique une carte électronique accrochée au mur lol

bonsoir
je déterre ce topic , parce que j'ai petit problème.
je me suis servis des conseils de heloderma-krys , tout fonction a merveille , a l'exception de l' affichage de l'heure sur mon menu principal, qui reste figée.
elle change seulement quand je change de page .
j'ai aussi créé des boutons , pour faire changer d’état des relais , mais lorsque j'appuie dessus , l'action se fait mais la page entière est rafraichie .
j'ai créé des fonctions qui sont appelées dans la boucle LOOP via un switch case.
si vous pouvez m'éclairer ? ......

merci

Relis le message initial, il parle des affichages qui changent et ceux qui ne changent pas. Ton problème vient peut-être d'une mauvaise prise en compte à ce niveau là.
Sinon, poste un message sur le forum principal français, tu y auras plus de visibilité