{"id":1478,"date":"2021-06-04T14:15:55","date_gmt":"2021-06-04T13:15:55","guid":{"rendered":"https:\/\/blog.univ-angers.fr\/istiaprojetsei2\/?p=1478"},"modified":"2021-06-16T15:50:03","modified_gmt":"2021-06-16T14:50:03","slug":"display-box","status":"publish","type":"post","link":"https:\/\/blog.univ-angers.fr\/polytech_2A\/2021\/06\/04\/display-box\/","title":{"rendered":"Display box"},"content":{"rendered":"<p><strong>Bonjour \u00e0 tous,<\/strong><\/p>\n<p>Nous sommes 4 \u00e9tudiants de PeiP 2, Th\u00e9o ROY, Zacharie FOURRIER, Alexandre PRAT et Eli DESTOMBES.<br \/>\nDans le cadre de notre projet de conception nous avons travaill\u00e9 sur une display-box.<br \/>\nL&#8217;objectif de notre projet est de r\u00e9aliser diff\u00e9rents programmes qui g\u00e8rent des \u00e9crans dans le but de les int\u00e9grer \u00e0 un projet d&#8217;escape Game.<br \/>\nNous avons tous travaill\u00e9 sur Arduino mais aussi sur AppInventor ou python pour certains.<br \/>\nNous avons donc r\u00e9alis\u00e9 5 mini-projets et nous allons vous montrer comment les utiliser !<\/p>\n<p><strong><font color=\"red\"> Projet n\u00b01 : Clavier tactile et code secret &#8211; R\u00e9alis\u00e9 par Eli DESTOMBES<\/font><\/strong><br \/>\nLe but de mon projet est de r\u00e9aliser un clavier tactile \u00e0 code secret qui avec le bon code va changer de fen\u00eatre pour afficher une nouvelle fen\u00eatre.<br \/>\nJe vais donc vous montrer comment le coder.<\/p>\n<p>Mot cl\u00e9 : 2.4 \u2018\u2019 TFT LCD SHIELD, Arduino, clavier tactile , clavier azerty <\/p>\n<p><strong>1\u00e8re \u00c9tape : Pr\u00e9paration<\/strong><br \/>\n<em>1.1 Les librairies <\/em><\/p>\n<p>Pour ce qui est du mat\u00e9riel j\u2019ai utilis\u00e9 un \u00e9cran 2.4 \u2018\u2019 TFT LCD SHIELD et une carte Arduino UNO<br \/>\nMaintenant voici les librairies Arduino que nous allons utiliser : <\/p>\n<p>&#8211; Adafruit GFX <div id=\"attachment_1825\" style=\"width: 615px\" class=\"wp-caption alignnone\"><a href=\"https:\/\/blog.univ-angers.fr\/istiaprojetsei2\/files\/2021\/06\/unknown2.png\"><img loading=\"lazy\" decoding=\"async\" aria-describedby=\"caption-attachment-1825\" src=\"https:\/\/blog.univ-angers.fr\/istiaprojetsei2\/files\/2021\/06\/unknown2.png\" alt=\"Vous pouvez l\u2019installer depuis Arduino, pour cela faite \u00ab Ctrl+Maj+I \u00bb pour ouvrir le gestionnaire de biblioth\u00e8ques puis cherchez Adafruit GFX. Elle fournit une syntaxe et un ensemble de fonction graphiques pour les \u00e9crans LCD et OLED\" width=\"605\" height=\"98\" class=\"size-full wp-image-1825\" srcset=\"https:\/\/blog.univ-angers.fr\/polytech_2A\/files\/2021\/06\/unknown2.png 605w, https:\/\/blog.univ-angers.fr\/polytech_2A\/files\/2021\/06\/unknown2-300x48.png 300w, https:\/\/blog.univ-angers.fr\/polytech_2A\/files\/2021\/06\/unknown2-500x80.png 500w\" sizes=\"auto, (max-width: 605px) 100vw, 605px\" \/><\/a><p id=\"caption-attachment-1825\" class=\"wp-caption-text\">Vous pouvez l\u2019installer depuis Arduino, pour cela faite \u00ab Ctrl+Maj+I \u00bb pour ouvrir le gestionnaire de biblioth\u00e8que puis chercher Adafruit GFX.<br \/>Elle fournit une syntaxe et un ensemble de fonction graphique pour les \u00e9crans LCD et OLED<\/p><\/div><br \/>\n&#8211; Adafruit TFTLCD <div id=\"attachment_1826\" style=\"width: 615px\" class=\"wp-caption alignnone\"><a href=\"https:\/\/blog.univ-angers.fr\/istiaprojetsei2\/files\/2021\/06\/unknown-11.png\"><img loading=\"lazy\" decoding=\"async\" aria-describedby=\"caption-attachment-1826\" src=\"https:\/\/blog.univ-angers.fr\/istiaprojetsei2\/files\/2021\/06\/unknown-11.png\" alt=\"De la m\u00eame fa\u00e7on, vous la trouverez dans le gestionnaire de biblioth\u00e8ques en cherchant Adafruit TFTLCD. Pour v\u00e9rifier que la biblioth\u00e8que est bien install\u00e9e et que votre \u00e9cran fonctionne, allez dans Fichier -&gt; Example -&gt; Adafruit TFTLCD Library -&gt; graphictest puis ex\u00e9cutez le programme\" width=\"605\" height=\"82\" class=\"size-full wp-image-1826\" srcset=\"https:\/\/blog.univ-angers.fr\/polytech_2A\/files\/2021\/06\/unknown-11.png 605w, https:\/\/blog.univ-angers.fr\/polytech_2A\/files\/2021\/06\/unknown-11-300x40.png 300w, https:\/\/blog.univ-angers.fr\/polytech_2A\/files\/2021\/06\/unknown-11-500x67.png 500w\" sizes=\"auto, (max-width: 605px) 100vw, 605px\" \/><\/a><p id=\"caption-attachment-1826\" class=\"wp-caption-text\">De la m\u00eame fa\u00e7on, vous la trouverez dans le gestionnaire de biblioth\u00e8que en cherchant Adafruit TFTLCD. Pour v\u00e9rifier que la biblioth\u00e8que est bien install\u00e9e et que votre \u00e9cran fonctionne, allez dans Fichier -&gt; Example -&gt; Adafruit TFTLCD Library -&gt; graphictest puis ex\u00e9cutez le programme<\/p><\/div><br \/>\n&#8211; Adafruit TouchScreen <div id=\"attachment_1827\" style=\"width: 615px\" class=\"wp-caption alignnone\"><a href=\"https:\/\/blog.univ-angers.fr\/istiaprojetsei2\/files\/2021\/06\/unknown-2.png\"><img loading=\"lazy\" decoding=\"async\" aria-describedby=\"caption-attachment-1827\" src=\"https:\/\/blog.univ-angers.fr\/istiaprojetsei2\/files\/2021\/06\/unknown-2.png\" alt=\"De la m\u00eame fa\u00e7on vous la trouverez dans le gestionnaire de biblioth\u00e8ques en cherchant TouchScreen. Pour v\u00e9rifier que le tactile fonctionne, allez dans Fichier -&gt; Example -&gt; Adafruit TouchScreen -&gt; touchscreendemo puis ouvrir le moniteur s\u00e9rie et ex\u00e9cutez le programme. Appuyez sur l\u2019\u00e9cran et regarder le moniteur pour voir si des coordonn\u00e9es apparaissent. \" width=\"605\" height=\"87\" class=\"size-full wp-image-1827\" srcset=\"https:\/\/blog.univ-angers.fr\/polytech_2A\/files\/2021\/06\/unknown-2.png 605w, https:\/\/blog.univ-angers.fr\/polytech_2A\/files\/2021\/06\/unknown-2-300x43.png 300w, https:\/\/blog.univ-angers.fr\/polytech_2A\/files\/2021\/06\/unknown-2-500x71.png 500w\" sizes=\"auto, (max-width: 605px) 100vw, 605px\" \/><\/a><p id=\"caption-attachment-1827\" class=\"wp-caption-text\">De la m\u00eame fa\u00e7on vous la trouverez dans le gestionnaire de biblioth\u00e8que en cherchant TouchScreen. Pour v\u00e9rifier que le tactile fonctionne, allez dans Fichier -&gt; Example -&gt; Adafruit TouchScreen -&gt; touchscreendemo puis ouvrir le moniteur s\u00e9rie et ex\u00e9cutez le programme. Appuyez sur l\u2019\u00e9cran et regardez le moniteur pour voir si des coordonn\u00e9es apparaissent.<\/p><\/div><br \/>\n&#8211; String<br \/>\nLa librairie <strong>String.h<\/strong> est install\u00e9e de base sur Arduino<\/p>\n<p><em>1.2 D\u00e9finitions des PINs <\/em><br \/>\nPIN pour l\u2019\u00e9cran<br \/>\n<code><br \/>\n#define LCD_CS A3 \/\/ Chip Select va vers Analog 3<br \/>\n#define LCD_CD A2 \/\/ Command\/Data va vers Analog 2<br \/>\n#define LCD_WR A1 \/\/ LCD Write va vers Analog 1<br \/>\n#define LCD_RD A0 \/\/ LCD Read va vers Analog 0<br \/>\n#define LCD_RESET A4<br \/>\n<\/code><br \/>\nPIN pour la position du tactile<\/p>\n<p><code>#define YP A2<br \/>\n#define XM A3<br \/>\n#define YM 8<br \/>\n#define XP 9<\/code><\/p>\n<p><em>1.3 D\u00e9finition des coordonn\u00e9es max et min pour un \u00e9cran 2.4 \u2018\u2019 TFT <\/em><\/p>\n<p><code>#define TS_MINX 204<br \/>\n#define TS_MINY 195<br \/>\n#define TS_MAXX 948<br \/>\n#define TS_MAXY 910<\/code><\/p>\n<p>Nous allons aussi utiliser diff\u00e9rentes couleurs, il est donc utile de d\u00e9finir les couleurs que vous allez utiliser avec :<br \/>\n<code>#define nom_de_la_couleur code_hexa_de_la_couleur <\/code><\/p>\n<p><strong>2\u00e8me \u00c9tape : Trouver le driver LCD <\/strong><\/p>\n<p>C\u2019est une \u00e9tape importante car sans le bon driver l\u2019\u00e9cran ne peut pas marcher, pour trouver le bon driver il faut ouvrir le programme d\u2019exemple tftbpm qui est dans Adafruit TFTLCD Library.<br \/>\nIl faut ouvrir le moniteur s\u00e9rie et lancer le programme (avec votre \u00e9cran connect\u00e9 \u00e0 l\u2019Arduino).<br \/>\nDans le moniteur une ligne apparait :  Found ILI9341 LCD driver (ou un autre code), ensuite il faut aller chercher dans le code pour trouver le code hexad\u00e9cimal du driver<br \/>\n<a href=\"https:\/\/blog.univ-angers.fr\/istiaprojetsei2\/files\/2021\/06\/unknown-4.png\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/blog.univ-angers.fr\/istiaprojetsei2\/files\/2021\/06\/unknown-4.png\" alt=\"\" width=\"314\" height=\"92\" class=\"alignnone size-full wp-image-1828\" srcset=\"https:\/\/blog.univ-angers.fr\/polytech_2A\/files\/2021\/06\/unknown-4.png 314w, https:\/\/blog.univ-angers.fr\/polytech_2A\/files\/2021\/06\/unknown-4-300x87.png 300w\" sizes=\"auto, (max-width: 314px) 100vw, 314px\" \/><\/a><br \/>\nUne fois le driver trouv\u00e9 il faut \u00e9crire dans le void setup() :<br \/>\n <code>tft.begin(0x9341);<\/code><br \/>\nIl faudra aussi \u00e9crire cette ligne avant le void setup() pour que l\u2019\u00e9cran fonctionne :<br \/>\n<code>Adafruit_TFTLCD tft(LCD_CS, LCD_CD, LCD_WR, LCD_RD, LCD_RESET);<\/code><br \/>\nIl est possible que le programme ne fonctionne pas correctement et que le moniteur ne trouve pas le driver. C\u2019est un probl\u00e8me que j\u2019ai eu et pour le r\u00e9soudre j\u2019ai suivi cette vid\u00e9o :<br \/>\n<a href=\"https:\/\/www.youtube.com\/watch?v=Tj-DjKAp770\">https:\/\/www.youtube.com\/watch?v=Tj-DjKAp770<\/a><\/p>\n<p><strong>3\u00e8me \u00c9tape : affichage du clavier <\/strong><\/p>\n<p><a href=\"https:\/\/blog.univ-angers.fr\/istiaprojetsei2\/files\/2021\/06\/unknown-3.png\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/blog.univ-angers.fr\/istiaprojetsei2\/files\/2021\/06\/unknown-3.png\" alt=\"\" width=\"307\" height=\"224\" class=\"alignnone size-full wp-image-1830\" srcset=\"https:\/\/blog.univ-angers.fr\/polytech_2A\/files\/2021\/06\/unknown-3.png 307w, https:\/\/blog.univ-angers.fr\/polytech_2A\/files\/2021\/06\/unknown-3-300x218.png 300w\" sizes=\"auto, (max-width: 307px) 100vw, 307px\" \/><\/a><br \/>\nPour l\u2019affichage du clavier j\u2019ai cr\u00e9\u00e9 une fonction clavier() que j\u2019utilise dans le void setup(), comme cela elle va apparaitre au d\u00e9marrage du programme.<\/p>\n<p><em>3.1 Affichage des rectangles <\/em><\/p>\n<p>Pour dessiner les cases autours des lettres j\u2019ai utilis\u00e9 la fonction tft.drawRect qui se construit de la fa\u00e7ons suivante :<br \/>\n<code>tft.drawRect( x, y, l, h, COLOR) ;<\/code><br \/>\nAvec :<br \/>\n\u2022       x : coordonn\u00e9e en x du point de d\u00e9part du rectangle<br \/>\n\u2022\ty : coordonn\u00e9e en y du point de d\u00e9part du rectangle<br \/>\n\u2022\tl : la largeur du rectangle<br \/>\n\u2022\th : la hauteur du rectangle<br \/>\n\u2022\tCOLOR : la couleur du rectangle<br \/>\nCela va cr\u00e9er un rectangle vide avec un contour de la couleur choisie. <\/p>\n<p>Si vous voulez un rectangle rempli il faut utiliser la fonction tft.fillRect qui se construit de la m\u00eame fa\u00e7on que tft.drawRect :<br \/>\n<code>tft.fillRect( x, y, l, h, COLOR) ; <\/code><br \/>\nAvec :<br \/>\n\u2022\tx : coordonn\u00e9e en x du point de d\u00e9part du rectangle<br \/>\n\u2022\ty : coordonn\u00e9e en y du point de d\u00e9part du rectangle<br \/>\n\u2022\tl : la largeur du rectangle<br \/>\n\u2022\th : la hauteur du rectangle<br \/>\n\u2022\tCOLOR : la couleur du rectangle <\/p>\n<p><em>3.2 Affichage du texte <\/em><\/p>\n<p>Pour \u00e9crire du texte nous allons avoir besoin de 5 fonctions.<br \/>\nLa premi\u00e8re est tft.setCursor qui sert \u00e0 placer le point de d\u00e9part du texte :<br \/>\n<code>tft.setCursor( x, y) ;<\/code><br \/>\nAvec :<br \/>\n\u2022\tx : coordonn\u00e9e x du point de d\u00e9part<br \/>\n\u2022\ty : coordonn\u00e9e y du point de d\u00e9part   <\/p>\n<p>Ensuite il y a tft.TextColor qui va changer la couleur du texte :<br \/>\n<code>tft.setTextColor(COLOR) ;<\/code><br \/>\nAvec :<br \/>\n\u2022\tCOLOR : couleur du texte<\/p>\n<p>Puis, pour g\u00e9rer la taille du texte il y a la fonction tft.setTextSize :<br \/>\n\t<code>tft.setTextSize(n) ;<\/code><br \/>\nAvec :<br \/>\n\u2022\tn : un entier compris entre 1 et 5. La taille de base est de 1 et chaque augmentation de 1 augmente la hauteur du texte de 10 pixels. <\/p>\n<p>Enfin pour \u00e9crire du texte, il existe deux fonctions.<br \/>\n\tLa premi\u00e8re, tft.print ou tft.println  , qui \u00e9crit tous les caract\u00e8res non sp\u00e9ciaux<br \/>\n\t\t<code>tft.println(\u201c \u201d) ;<\/code><br \/>\n\tLa deuxi\u00e8me, tft.write , qui permet d\u2019\u00e9crire des caract\u00e8res sp\u00e9ciaux avec leur code hexad\u00e9cimal<br \/>\n\t\t<code>tft.write(0xXX) ;<\/code><\/p>\n<p>Exemple de cr\u00e9ation d\u2019une touche du clavier :<br \/>\n  <code>tft.drawRect(6, 120, 28, 36, RED); \/\/ on utilise 2 fois la fonction drawRect<br \/>\n  tft.drawRect(7, 121, 26, 34, RED); \/\/ pour faire une plus grosse \u00e9paisseur<br \/>\n  tft.setCursor(10, 125); \/\/ on place le curseur a la postition 10 x , 125 y<br \/>\n  tft.setTextColor(WHITE); \/\/ on met le texte en blanc<br \/>\n  tft.setTextSize(4); \/\/ on met le texte de taille 4<br \/>\n  tft.print(\"A\"); \/\/ on \u00e9crit le caract\u00e8re A<\/code><\/p>\n<p><strong>4\u00e8me \u00c9tape : Position sur l\u2019\u00e9cran et chaine de caract\u00e8res <\/strong><\/p>\n<p>Pour commencer, il faut d\u00e9clarer ces lignes avant le void setup() pour que les fonctions de position marchent :<br \/>\n<code>TouchScreen ts = TouchScreen(XP, YP, XM, YM, 300);<br \/>\nboolean buttonEnabled = true;<\/code><\/p>\n<p>On d\u00e9clare une variable buttonEnabled qui va nous servir plus tard pour nos touches.<br \/>\net pour que notre chaine de caract\u00e8res fonctionne :<br \/>\n<code>String chaineCara;<\/code> <\/p>\n<p><em>4.1 Affichage d\u2019un caract\u00e8re <\/em><\/p>\n<p>Pour cette partie on va cr\u00e9er une nouvelle fonction menu()<br \/>\nOn commence par \u00e9crire <code>TSPoint p = ts.getPoint();<\/code> qui nous permet de r\u00e9cup\u00e9rer la position de l\u2019appui sur l\u2019\u00e9cran.<br \/>\nLa librairie TouchScreen fonctionne avec 3 coordonn\u00e9es, x ,y et z. Pour d\u00e9tecter un appui on se sert de la position Z comme cela : <\/p>\n<p><code>if (p.z &gt; ts.pressureThreshhold) {<\/p>\n<p>      p.x = map(p.x, TS_MAXX, TS_MINX, 0, 320);<br \/>\n      p.y = map(p.y, TS_MAXY, TS_MINY, 0, 240);<\/p>\n<p>      Serial.print(\"X = \"); Serial.print(p.x);<br \/>\n      Serial.print(\"\\tY = \"); Serial.print(p.y);<br \/>\n      Serial.print(\"\\n\");<br \/>\n\u2026<\/code><\/p>\n<p>La fonction map permet de bouger un intervalle de valeurs vers un autre,<br \/>\n<code>map(value, fromLow, fromHigh, toLow, toHigh)<\/code><br \/>\nAvec :<br \/>\n\u2022value: le nombre \u00e0 \u201cmapper\u201d<br \/>\n\u2022fromLow: La borne inf\u00e9rieure de la valeur actuelle<br \/>\n\u2022fromHigh: La borne sup\u00e9rieure de la valeur actuelle<br \/>\n\u2022toLow: La borne inf\u00e9rieure de la valeur vis\u00e9e<br \/>\n\u2022toHigh: La borne sup\u00e9rieure de la valeur vis\u00e9e<\/p>\n<p>On l\u2019utilise ici pour replacer entre 0 et 320 pour x et entre 0 et 240 pour y car<br \/>\nIci quand on va appuyer sur l\u2019\u00e9cran on va avoir la position x et y,<br \/>\nPour d\u00e9finir la zone d\u2019appui d\u2019une lettre j\u2019ai utilis\u00e9 ceci :<br \/>\n<code>if (p.x &gt; 6 &amp;&amp; p.x  80 &amp;&amp; p.y  37 &amp;&amp; p.x  80 &amp;&amp; p.y &lt; 120 &amp;&amp; buttonEnabled) {<\/p>\n<p>        pinMode(XM, OUTPUT);<br \/>\n        pinMode(YP, OUTPUT);<\/p>\n<p>        chaineCara = chaineCara + &quot;Z&quot;;<br \/>\n        longueur  = chaineCara.length();<\/code><br \/>\net on continue avec des else if pour chaque touche que l\u2019on a cr\u00e9\u00e9e.<br \/>\n<em><br \/>\n4.2 Suppression d\u2019un caract\u00e8re <\/em><\/p>\n<p>Pour supprimer un caract\u00e8re j\u2019utilise ceci :<br \/>\n<code>chaineCara = chaineCara.substring(0, longueur - 1);<\/code><br \/>\ncette ligne permet de retirer un caract\u00e8re dans la chaine mais pas sur l\u2019\u00e9cran, il faut donc aussi le supprimer \u00e0 l\u2019\u00e9cran.<br \/>\nPour cela je cr\u00e9e des rectangles de la couleur du fond que je superpose avec les lettres pour les effacer.<br \/>\n<code>if (longueur == 8 ) {<br \/>\n          tft.fillRect(213, 30, 24, 30, BLACK);<br \/>\n        } else if (longueur == 7 ) {<br \/>\n          tft.fillRect(189, 30, 24, 30, BLACK);<br \/>\n        }<br \/>\n        else if (longueur == 6) {<br \/>\n          tft.fillRect(165, 30, 24, 30, BLACK);<br \/>\n        }<br \/>\n        else if (longueur == 5 ) {<br \/>\n          tft.fillRect(141, 30, 24, 30, BLACK);<br \/>\n        }<br \/>\n        else if (longueur == 4 ) {<br \/>\n          tft.fillRect(117, 30, 24, 30, BLACK);<br \/>\n        }<br \/>\n        else if (longueur == 3 ) {<br \/>\n          tft.fillRect(93, 30, 24, 30, BLACK);<br \/>\n        }<br \/>\n        else if (longueur == 2 ) {<br \/>\n          tft.fillRect(69, 30, 24, 30, BLACK);<br \/>\n        }<br \/>\n        else if (longueur == 1 ) {<br \/>\n          tft.fillRect(45, 30, 24, 30, BLACK);<br \/>\n        }<br \/>\n      }<\/code><\/p>\n<p><em>4.3 Limiter la taille de la chaine de caract\u00e8res <\/em><\/p>\n<p>Pour limiter la taille de la chaine de caract\u00e8res, j\u2019ai fait un if qui encadre tout ce que nous avons fait dans la partie 4 :<br \/>\n<code>unsigned long menu() {<br \/>\n  int longueur = 0 ;<br \/>\n  TSPoint p = ts.getPoint();  \/\/Get touch point<br \/>\n  longueur  = chaineCara.length(); \/\/ calcul de la longueur de la chaine<br \/>\n  if (longueur &lt; 9) { \/\/on limite la taille de la chaine \u00e0 9<br \/>\n\u2026 \/\/ code du 4.1 et 4.2<br \/>\n} else {<br \/>\n    chaineCara = chaineCara + \"\" ; \/\/on ajoute rien a la chaine<br \/>\n    if (p.z &gt; ts.pressureThreshhold) {<br \/>\n      p.x = map(p.x, TS_MAXX, TS_MINX, 0, 320);<br \/>\n      p.y = map(p.y, TS_MAXY, TS_MINY, 0, 240);<br \/>\n      if (p.x &gt; 192 &amp;&amp; p.x &lt; 220 &amp;&amp; p.y &gt; 1 &amp;&amp; p.y &lt; 40 &amp;&amp; buttonEnabled) {<br \/>\n   pinMode(XM, OUTPUT);<br \/>\n        pinMode(YP, OUTPUT);<br \/>\n        chaineCara = chaineCara.substring(0, longueur - 1);<\/p>\n<p>        if (longueur == 9 ) {<br \/>\n          tft.fillRect(237, 30, 24, 30, BLACK);<br \/>\n        }}}}}<br \/>\n<\/code><br \/>\n<strong>5\u00e8me \u00c9tape : void setup et void loop <\/strong><br \/>\n<em><br \/>\n5.1 construction du void setup()<\/em><br \/>\n<code><br \/>\nvoid setup() {<br \/>\n  tft.reset(); \/\/reset l\u2019\u00e9cran<br \/>\n  tft.begin(0x9341); \/\/ voir \u00e9tapes 2<br \/>\n  Serial.begin(9600); la valeur doit \u00eatre la m\u00eame que celle du moniteur<br \/>\n  tft.setRotation(3); \/\/ rotation de 0,90,180,270\u00b0 respectivement 0,1,2,3<br \/>\n  tft.fillScreen(BLACK); \/\/ remplis d\u2019\u00e9cran de noir<br \/>\n  rectangle();\/\/fonction qui cr\u00e9e le grand rectangle du milieu<br \/>\n  clavier(); \/\/ fonction de l\u2019\u00e9tape 4<br \/>\n}<\/code><\/p>\n<p><em>5.2 construction du void loop(void)<\/em><\/p>\n<p><code>void loop(void) {<br \/>\n  menu() ;<br \/>\n  if (chaineCara == \"CODEBON\") { \/\/on v\u00e9rifie que la chaine correspond au<br \/>\n   \/\/code<br \/>\n     buttonEnabled = false; \/\/on d\u00e9sactive la variable buttonEnabled pour ne plus pouvoir appuyer sur les boutons une fois le code trouver<br \/>\n...<br \/>\n  }<br \/>\n  delay(100) ; \/\/ on met un petit d\u00e9lais pour ne pas doubler les lettres quand on appuie sur les boutons<br \/>\n}<br \/>\n<\/code><br \/>\nNous voil\u00e0 donc \u00e0 la fin de ce projet, voici une petite vid\u00e9o qui montre comment fonctionne le programme :<br \/>\n<a href=\"https:\/\/www.youtube.com\/embed\/8LQWGmZC6mI?feature=oembed\">https:\/\/www.youtube.com\/embed\/8LQWGmZC6mI?feature=oembed<\/a><\/p>\n<p><strong><font color=\"red\">Projet n\u00b02: Affichage LCD via Application Bluetooth &#8211; R\u00e9alis\u00e9 par Alexandre PRAT<\/strong><\/font><\/p>\n<p>Mot cl\u00e9 : ESP32, LCD I2C 16&#215;2, Arduino, AppInventor <\/p>\n<p><strong>1\u00e8re \u00c9tape : Pr\u00e9paration <\/strong><br \/>\n<em>1.1 Les librairies <\/em><\/p>\n<p>Voici les librairies que j\u2019ai d\u00fb utiliser :<br \/>\n&#8211; LiquidCrystal_I2C<br \/>\n<div id=\"attachment_1845\" style=\"width: 615px\" class=\"wp-caption alignnone\"><a href=\"https:\/\/blog.univ-angers.fr\/istiaprojetsei2\/files\/2021\/06\/unknown-5.png\"><img loading=\"lazy\" decoding=\"async\" aria-describedby=\"caption-attachment-1845\" src=\"https:\/\/blog.univ-angers.fr\/istiaprojetsei2\/files\/2021\/06\/unknown-5.png\" alt=\"Vous pouvez l\u2019installer depuis Arduino, pour cela faites \u00ab Ctrl+Maj+I \u00bb pour ouvrir le gestionnaire de biblioth\u00e8ques puis cherchez LiquidCrystal_I2C. Elle fournit diff\u00e9rentes fonctions permettant d\u2019utiliser l\u2019\u00e9cran LCD 16x2.\" width=\"605\" height=\"97\" class=\"size-full wp-image-1845\" srcset=\"https:\/\/blog.univ-angers.fr\/polytech_2A\/files\/2021\/06\/unknown-5.png 605w, https:\/\/blog.univ-angers.fr\/polytech_2A\/files\/2021\/06\/unknown-5-300x48.png 300w, https:\/\/blog.univ-angers.fr\/polytech_2A\/files\/2021\/06\/unknown-5-500x80.png 500w\" sizes=\"auto, (max-width: 605px) 100vw, 605px\" \/><\/a><p id=\"caption-attachment-1845\" class=\"wp-caption-text\">Vous pouvez l\u2019installer depuis Arduino, pour cela faites \u00ab Ctrl+Maj+I \u00bb pour ouvrir le gestionnaire de biblioth\u00e8ques puis cherchez LiquidCrystal_I2C.<br \/>Elle fournit diff\u00e9rentes fonctions permettant d\u2019utiliser l\u2019\u00e9cran LCD 16&#215;2.<\/p><\/div><br \/>\nJ\u2019utilise \u00e9galement les librairies <strong>wire.h<\/strong> et <strong>bluetoothserial.h<\/strong> qui sont d\u00e9j\u00e0 install\u00e9es d\u2019origine !<\/p>\n<p><em>1.2 Les branchements <\/em><\/p>\n<p>Pour commencer, branchez votre \u00e9cran LCD \u00e0 l\u2019esp32 via le module I2C comme pr\u00e9sent\u00e9 sur le sch\u00e9ma ci-dessous :<br \/>\n<a href=\"https:\/\/blog.univ-angers.fr\/istiaprojetsei2\/files\/2021\/06\/unknown-6.png\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/blog.univ-angers.fr\/istiaprojetsei2\/files\/2021\/06\/unknown-6.png\" alt=\"\" width=\"465\" height=\"231\" class=\"alignnone size-full wp-image-1846\" srcset=\"https:\/\/blog.univ-angers.fr\/polytech_2A\/files\/2021\/06\/unknown-6.png 465w, https:\/\/blog.univ-angers.fr\/polytech_2A\/files\/2021\/06\/unknown-6-300x149.png 300w\" sizes=\"auto, (max-width: 465px) 100vw, 465px\" \/><\/a><\/p>\n<p><em>1.3 Premiers essais <\/em><br \/>\nPour tester les branchements et le fonctionnement de l\u2019\u00e9cran LCD, voici un premier programme de test permettant d\u2019afficher \u00ab Hello, world ! \u00bb sur l\u2019\u00e9cran LCD :<br \/>\n<code><br \/>\n#include &lt;Wire.h&gt;<br \/>\n#include &lt;LiquidCrystal_I2C.h&gt;<\/p>\n<p>LiquidCrystal_I2C lcd(0x27,16,2);  \/\/ set the LCD address to 0x27 for a 16 chars and 2 line display \/\/ intervertir avec la ligne suivante si cela ne fonctionne pas<br \/>\n\/\/LiquidCrystal_I2C lcd(0x3F,16,2);<\/p>\n<p>void setup()<br \/>\n{<br \/>\n  lcd.init();                   \/\/ initialize the lcd <\/p>\n<p>  \/\/ Print a message to the LCD.<br \/>\n  lcd.backlight();<br \/>\n  lcd.print(\"Hello, world!\");<br \/>\n}<br \/>\nvoid loop()<br \/>\n{<br \/>\n}<br \/>\n<\/code><br \/>\n<a href=\"https:\/\/univangersfr-my.sharepoint.com\/:u:\/g\/personal\/aprat_etud_univ-angers_fr\/ETuXsmyVzaNLhhckV4ArAuABKRGD0vT94XGYc4X-SkFDtg?e=zFpGZ9\">https:\/\/univangersfr-my.sharepoint.com\/:u:\/g\/personal\/aprat_etud_univ-angers_fr\/ETuXsmyVzaNLhhckV4ArAuABKRGD0vT94XGYc4X-SkFDtg?e=zFpGZ9<\/a><\/p>\n<p>Si cela ne fonctionne pas, vous pouvez commenter le ligne \u00ab LiquidCrystal_I2C lcd(0x27,16,2); \u00bb et d\u00e9commenter la ligne \u00ab \/\/LiquidCrystal_I2C lcd(0x3F,16,2); \u00bb .<\/p>\n<p>Si cela ne r\u00e8gle pas votre probl\u00e8me, vous pourrez ex\u00e9cuter le programme ci-dessous, en rempla\u00e7ant 0x27 ou 0x3F par le code hexad\u00e9cimal affich\u00e9 dans le moniteur s\u00e9rie :<br \/>\n<code><br \/>\n#include &lt;Wire.h&gt;<\/p>\n<p>void setup() {<br \/>\n  Wire.begin();<br \/>\n  Serial.begin(115200);<br \/>\n  Serial.println(\"\\nI2C Scanner\");<br \/>\n}<br \/>\nvoid loop() {<br \/>\n  byte error, address;<br \/>\n  int nDevices;<br \/>\n  Serial.println(\"Scanning...\");<br \/>\n  nDevices = 0;<br \/>\n  for(address = 1; address &lt; 127; address++ ) {<br \/>\n    Wire.beginTransmission(address);<br \/>\n    error = Wire.endTransmission();<br \/>\n    if (error == 0) {<br \/>\n      Serial.print(&quot;I2C device found at address 0x&quot;);<br \/>\n      if (address&lt;16) {<br \/>\n        Serial.print(&quot;0&quot;);<br \/>\n      }<br \/>\n      Serial.println(address,HEX);<br \/>\n      nDevices++;<br \/>\n    }<br \/>\n    else if (error==4) {<br \/>\n      Serial.print(&quot;Unknow error at address 0x&quot;);<br \/>\n      if (address&lt;16) {<br \/>\n        Serial.print(&quot;0&quot;);<br \/>\n      }<br \/>\n      Serial.println(address,HEX);<br \/>\n    }<br \/>\n  }<br \/>\n  if (nDevices == 0) {<br \/>\n    Serial.println(&quot;No I2C devices found\\n&quot;);<br \/>\n  }<br \/>\n  else {<br \/>\n    Serial.println(&quot;done\\n&quot;);<br \/>\n  }<br \/>\n  delay(5000);<br \/>\n}<br \/>\n<\/code><br \/>\n<a href=\"https:\/\/univangersfr-my.sharepoint.com\/:u:\/g\/personal\/aprat_etud_univ-angers_fr\/EVvGIcGU3LFHtAuZYZxs28ABRLtZ7SlWSmjyNEjG5CjP8w?e=hcpthX\">https:\/\/univangersfr-my.sharepoint.com\/:u:\/g\/personal\/aprat_etud_univ-angers_fr\/EVvGIcGU3LFHtAuZYZxs28ABRLtZ7SlWSmjyNEjG5CjP8w?e=hcpthX<\/a><\/p>\n<p>Nous allons ensuite tester le fonctionnement du Bluetooth.<br \/>\nPour cela, vous pourrez utiliser cette application sur Android ainsi que le programme Arduino ci-dessous :<br \/>\n<a href=\"https:\/\/blog.univ-angers.fr\/istiaprojetsei2\/files\/2021\/06\/unknown-8.png\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/blog.univ-angers.fr\/istiaprojetsei2\/files\/2021\/06\/unknown-8.png\" alt=\"\" width=\"228\" height=\"174\" class=\"alignnone size-full wp-image-1848\" \/><\/a><br \/>\n<code>#include \"BluetoothSerial.h\"<\/p>\n<p>#if !defined(CONFIG_BT_ENABLED) || !defined(CONFIG_BLUEDROID_ENABLED)<br \/>\n#error Bluetooth is not enabled! Please run `make menuconfig` to and enable it<br \/>\n#endif<\/p>\n<p>BluetoothSerial SerialBT;<\/p>\n<p>void setup() {<br \/>\n  Serial.begin(115200);<br \/>\n  SerialBT.begin(\"ESP32test\"); \/\/Bluetooth device name<br \/>\n  Serial.println(\"The device started, now you can pair it with bluetooth!\");<br \/>\n}<br \/>\nvoid loop() {<br \/>\n  if (Serial.available()) {<br \/>\n    SerialBT.write(Serial.read());<br \/>\n  }<br \/>\n  if (SerialBT.available()) {<br \/>\n    Serial.write(SerialBT.read());<br \/>\n  }<br \/>\n  delay(20);<br \/>\n}<\/code><br \/>\n<a href=\"https:\/\/univangersfr-my.sharepoint.com\/:u:\/g\/personal\/aprat_etud_univ-angers_fr\/EVSxL8CWqXlHiVZMeacIWRABi6HBYXDStQy9AIILgsVhng?e=KFib9E\">https:\/\/univangersfr-my.sharepoint.com\/:u:\/g\/personal\/aprat_etud_univ-angers_fr\/EVSxL8CWqXlHiVZMeacIWRABi6HBYXDStQy9AIILgsVhng?e=KFib9E<\/a><\/p>\n<p>Pour tester le fonctionnement du Bluetooth, il vous suffit d\u2019ex\u00e9cuter ce programme sur votre ESP32, d\u2019ouvrir le moniteur s\u00e9rie Arduino,<br \/>\n<a href=\"https:\/\/blog.univ-angers.fr\/istiaprojetsei2\/files\/2021\/06\/unknown-9.png\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/blog.univ-angers.fr\/istiaprojetsei2\/files\/2021\/06\/unknown-9-300x57.png\" alt=\"\" width=\"300\" height=\"57\" class=\"alignnone size-medium wp-image-1849\" srcset=\"https:\/\/blog.univ-angers.fr\/polytech_2A\/files\/2021\/06\/unknown-9-300x57.png 300w, https:\/\/blog.univ-angers.fr\/polytech_2A\/files\/2021\/06\/unknown-9.png 484w\" sizes=\"auto, (max-width: 300px) 100vw, 300px\" \/><\/a><br \/>\npuis de connecter votre t\u00e9l\u00e9phone \u00e0 l\u2019esp32 en Bluetooth depuis le t\u00e9l\u00e9phone et ensuite depuis l\u2019application Serial Bluetooth Terminal.<br \/>\nUne fois correctement connect\u00e9, vour pourrez \u00e9crire sur le terminal de votre t\u00e9l\u00e9phone pour l\u2019afficher sur le moniteur s\u00e9rie Arduino et inversement !<\/p>\n<p><em>1.4 Installer l\u2019application :<\/em><\/p>\n<p>Pour transmettre du texte \u00e0 l\u2019\u00e9cran LCD en Bluetooth, j\u2019utilise une application Android que j\u2019ai r\u00e9alis\u00e9 sur AppInventor.<br \/>\nVoici le lien de l\u2019installateur de l\u2019application (.apk) :<br \/>\n<a href=\"https:\/\/univangersfr-my.sharepoint.com\/:u:\/g\/personal\/aprat_etud_univ-angers_fr\/EWnFDQ8-9ulKq7KXiemOuLEBS2T5Pe0Ow2qJs4uENpjz-w?e=ztpkF3\">https:\/\/univangersfr-my.sharepoint.com\/:u:\/g\/personal\/aprat_etud_univ-angers_fr\/EWnFDQ8-9ulKq7KXiemOuLEBS2T5Pe0Ow2qJs4uENpjz-w?e=ztpkF3<\/a><\/p>\n<p><strong>2\u00e8me \u00c9tape : Tester l\u2019application finale !<\/strong><\/p>\n<p>Maintenant la pr\u00e9paration termin\u00e9e, nous allons pouvoir utiliser tout ce potentiel dans la r\u00e9alisation de mon applicatif final !<br \/>\nIl s\u2019agit en effet d\u2019afficher du texte sur l\u2019\u00e9cran LCD 16&#215;2, et ce en l\u2019envoyant en Bluetooth via l\u2019application que j\u2019ai r\u00e9alis\u00e9.<br \/>\nVoici le programme Arduino \u00e0 t\u00e9l\u00e9verser sur l\u2019ESP32 :<br \/>\n<code>#include &lt;Wire.h&gt;<br \/>\n#include &lt;LiquidCrystal_I2C.h&gt;<br \/>\n#include &lt;BluetoothSerial.h&gt;<\/p>\n<p>#if !defined(CONFIG_BT_ENABLED) || !defined(CONFIG_BLUEDROID_ENABLED)<br \/>\n#error Bluetooth is not enabled! Please run `make menuconfig` to and enable it<br \/>\n#endif<\/p>\n<p>LiquidCrystal_I2C lcd(0x27,16,2); \/\/intervertir avec la ligne suivante si cela ne fonctionne pas<br \/>\n\/\/LiquidCrystal_I2C lcd(0x3F,16,2); <\/p>\n<p>BluetoothSerial SerialBT;<\/p>\n<p>char message[64];<br \/>\nString chaine = \"\";<br \/>\nint len, i;<\/p>\n<p>void my_fflush();<\/p>\n<p>void setup(){<br \/>\n  \/\/Initialisation du moniteur s\u00e9rie, bluetooth et de l'\u00e9cran LCD<br \/>\n  Serial.begin(115200);<br \/>\n  SerialBT.begin(\"LCD\");<br \/>\n  Serial.println(\"The device started, now you can pair it with bluetooth!\");<\/p>\n<p>  lcd.init();<br \/>\n  lcd.backlight();<br \/>\n}<br \/>\nvoid loop() {<br \/>\n    i = 1;<br \/>\n    \/\/Si l'on re\u00e7oit du texte en Bluetooth, on enregistre un par un chaque caract\u00e8re dans la variable message<br \/>\n    \/\/puis on incr\u00e9mente le string chaine de message<br \/>\n    while(SerialBT.available()) {<br \/>\n        if(i == 1) {<br \/>\n          chaine = \"\";<br \/>\n          lcd.clear();<br \/>\n          i = 0;<br \/>\n        }<br \/>\n        char message = SerialBT.read();<\/p>\n<p>        chaine += message;<\/p>\n<p>        Serial.println(chaine);<\/p>\n<p>        delay(20);<br \/>\n    }  <\/p>\n<p>    \/\/On converti ensuite le string chaine en un tableau de char<br \/>\n    chaine.toCharArray(message, 64);<\/p>\n<p>    \/\/on r\u00e9cup\u00e8re la taille de notre message<br \/>\n    len = strlen(message);<\/p>\n<p>    \/\/Si la taille d\u00e9passe 32 caract\u00e8res, on affiche \u00e0 l'\u00e9cran que le message est trop long<br \/>\n    if(len &gt; 32) {<br \/>\n      chaine = \"Votre message est trop long !\";<br \/>\n    } else {<br \/>\n      \/\/Sinon, on affache chaque caract\u00e8res \u00e0 l'\u00e9cran dans l'ordre en changeant les coordonn\u00e9es du curseur<br \/>\n        for (i = 0; i &lt; len; i++) {<br \/>\n            if(i  15) lcd.setCursor(i - 16, 1);<br \/>\n            lcd.print(message[i]);<br \/>\n        }}}<br \/>\n<\/code><br \/>\n<a href=\"https:\/\/univangersfr-my.sharepoint.com\/:u:\/g\/personal\/aprat_etud_univ-angers_fr\/EfNvR5hHh45GnOPvx0GrycsBfZ_O01t7o7nZTzXV-uiJWw?e=oW9IoI\">https:\/\/univangersfr-my.sharepoint.com\/:u:\/g\/personal\/aprat_etud_univ-angers_fr\/EfNvR5hHh45GnOPvx0GrycsBfZ_O01t7o7nZTzXV-uiJWw?e=oW9IoI<\/a><\/p>\n<p>Pour utiliser mon application, il vous suffit de lancer l\u2019application en ayant au pr\u00e9alable activ\u00e9 le Bluetooth, de cliquer sur Connexion, de vous connecter \u00e0 l\u2019ESP32 d\u00e9sign\u00e9 par LCD dans la liste des appareils Bluetooth d\u00e9tectables.<br \/>\n<a href=\"https:\/\/blog.univ-angers.fr\/istiaprojetsei2\/files\/2021\/06\/unknown-10.png\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/blog.univ-angers.fr\/istiaprojetsei2\/files\/2021\/06\/unknown-10-168x300.png\" alt=\"\" width=\"168\" height=\"300\" class=\"alignnone size-medium wp-image-1850\" srcset=\"https:\/\/blog.univ-angers.fr\/polytech_2A\/files\/2021\/06\/unknown-10-168x300.png 168w, https:\/\/blog.univ-angers.fr\/polytech_2A\/files\/2021\/06\/unknown-10.png 239w\" sizes=\"auto, (max-width: 168px) 100vw, 168px\" \/><\/a><br \/>\nUne fois connect\u00e9, un message, une zone de texte et un bouton apparaitra sur l\u2019\u00e9cran de l\u2019application, il vous suffira donc maintenant d\u2019\u00e9crire du texte dans la zone de texte et d\u2019appuyer sur le bouton ci-apr\u00e8s.<br \/>\n<a href=\"https:\/\/blog.univ-angers.fr\/istiaprojetsei2\/files\/2021\/06\/unknown-111.png\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/blog.univ-angers.fr\/istiaprojetsei2\/files\/2021\/06\/unknown-111-168x300.png\" alt=\"\" width=\"168\" height=\"300\" class=\"alignnone size-medium wp-image-1851\" srcset=\"https:\/\/blog.univ-angers.fr\/polytech_2A\/files\/2021\/06\/unknown-111-168x300.png 168w, https:\/\/blog.univ-angers.fr\/polytech_2A\/files\/2021\/06\/unknown-111.png 238w\" sizes=\"auto, (max-width: 168px) 100vw, 168px\" \/><\/a><br \/>\nVous verrez ainsi appara\u00eetre votre message sur votre \u00e9cran LCD 16&#215;2.<br \/>\nAttention ! Veillez \u00e0 ce que votre message ne d\u00e9passe pas les 32 caract\u00e8res, sinon un message d\u2019erreur apparaitra sur votre \u00e9cran !<br \/>\n<a href=\"https:\/\/blog.univ-angers.fr\/istiaprojetsei2\/files\/2021\/06\/unknown-7.png\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/blog.univ-angers.fr\/istiaprojetsei2\/files\/2021\/06\/unknown-7-300x225.png\" alt=\"\" width=\"300\" height=\"225\" class=\"alignnone size-medium wp-image-1852\" srcset=\"https:\/\/blog.univ-angers.fr\/polytech_2A\/files\/2021\/06\/unknown-7-300x225.png 300w, https:\/\/blog.univ-angers.fr\/polytech_2A\/files\/2021\/06\/unknown-7.png 351w\" sizes=\"auto, (max-width: 300px) 100vw, 300px\" \/><\/a><\/p>\n<p><strong><font color=\"red\">Projet n\u00b03: Affichage Image et Vid\u00e9o \u00e9cran OLED 0.96\u2019\u2019- R\u00e9alis\u00e9 par Alexandre PRAT<\/strong><\/font><\/p>\n<p>Mot cl\u00e9 : ESP32 ,carte SD ,Python, GIF, Arduino, OLED SSD1315 0.96&#8221;, Frame <\/p>\n<p><strong>3.1 Image avec ESP32 et Carte SD<\/strong><br \/>\n<strong>1\u00e8re \u00c9tape : Pr\u00e9paration <\/strong><br \/>\n<em>1.1\tLes librairies<\/em> <\/p>\n<p>Voici les librairies que j\u2019ai d\u00fb utiliser :<br \/>\n&#8211; U8g2lib<br \/>\n<div id=\"attachment_1854\" style=\"width: 310px\" class=\"wp-caption alignnone\"><a href=\"https:\/\/blog.univ-angers.fr\/istiaprojetsei2\/files\/2021\/06\/unknown-12.png\"><img loading=\"lazy\" decoding=\"async\" aria-describedby=\"caption-attachment-1854\" src=\"https:\/\/blog.univ-angers.fr\/istiaprojetsei2\/files\/2021\/06\/unknown-12-300x92.png\" alt=\"Vous pouvez l\u2019installer depuis Arduino, pour cela, faites \u00ab Ctrl+Maj+I \u00bb pour ouvrir le gestionnaire de biblioth\u00e8que puis cherchez U8g2. Elle fournit diff\u00e9rentes fonctions permettant d\u2019utiliser diff\u00e9rents types d\u2019\u00e9crans dont notre \u00e9cran OLED SSD1315 0.96\u2019\u2019 \" width=\"300\" height=\"92\" class=\"size-medium wp-image-1854\" srcset=\"https:\/\/blog.univ-angers.fr\/polytech_2A\/files\/2021\/06\/unknown-12-300x92.png 300w, https:\/\/blog.univ-angers.fr\/polytech_2A\/files\/2021\/06\/unknown-12-500x153.png 500w, https:\/\/blog.univ-angers.fr\/polytech_2A\/files\/2021\/06\/unknown-12.png 605w\" sizes=\"auto, (max-width: 300px) 100vw, 300px\" \/><\/a><p id=\"caption-attachment-1854\" class=\"wp-caption-text\">Vous pouvez l\u2019installer depuis Arduino, pour cela, faites \u00ab Ctrl+Maj+I \u00bb pour ouvrir le gestionnaire de biblioth\u00e8que puis cherchez U8g2.<br \/>Elle fournit diff\u00e9rentes fonctions permettant d\u2019utiliser diff\u00e9rents types d\u2019\u00e9crans dont notre \u00e9cran <strong>OLED SSD1315 0.96\u2019\u2019<\/strong><br \/><\/p><\/div><br \/>\nJ\u2019utilise \u00e9galement les librairies <strong>Arduino.h, SPI.h<\/strong> et <strong>Wire.h<\/strong> qui sont d\u00e9j\u00e0 install\u00e9es d\u2019origine !<\/p>\n<p><em>1.2 Les branchements <\/em><\/p>\n<p>Pour commencer, branchez votre \u00e9cran OLED \u00e0 l\u2019esp32 comme pr\u00e9sent\u00e9 sur le sch\u00e9ma ci-dessous :<br \/>\n(L\u2019\u00e9cran est pr\u00e9vu pour fonctionner avec un module GROVE, mais vous pouvez simplement brancher des fils classiques dans le branchement GROVE et le brancher comme ci-contre)<br \/>\n<a href=\"https:\/\/blog.univ-angers.fr\/istiaprojetsei2\/files\/2021\/06\/unknown-13.png\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/blog.univ-angers.fr\/istiaprojetsei2\/files\/2021\/06\/unknown-13-300x225.png\" alt=\"\" width=\"300\" height=\"225\" class=\"alignnone size-medium wp-image-1855\" srcset=\"https:\/\/blog.univ-angers.fr\/polytech_2A\/files\/2021\/06\/unknown-13-300x225.png 300w, https:\/\/blog.univ-angers.fr\/polytech_2A\/files\/2021\/06\/unknown-13-399x300.png 399w, https:\/\/blog.univ-angers.fr\/polytech_2A\/files\/2021\/06\/unknown-13.png 498w\" sizes=\"auto, (max-width: 300px) 100vw, 300px\" \/><\/a><br \/>\nEnsuite, branchez votre module carte SD comme pr\u00e9sent\u00e9 sur le sch\u00e9ma ci-dessous :<a href=\"https:\/\/blog.univ-angers.fr\/istiaprojetsei2\/files\/2021\/06\/unknown-14.png\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/blog.univ-angers.fr\/istiaprojetsei2\/files\/2021\/06\/unknown-14-300x255.png\" alt=\"\" width=\"300\" height=\"255\" class=\"alignnone size-medium wp-image-1856\" srcset=\"https:\/\/blog.univ-angers.fr\/polytech_2A\/files\/2021\/06\/unknown-14-300x255.png 300w, https:\/\/blog.univ-angers.fr\/polytech_2A\/files\/2021\/06\/unknown-14-352x300.png 352w, https:\/\/blog.univ-angers.fr\/polytech_2A\/files\/2021\/06\/unknown-14.png 512w\" sizes=\"auto, (max-width: 300px) 100vw, 300px\" \/><\/a><br \/>\n<a href=\"https:\/\/blog.univ-angers.fr\/istiaprojetsei2\/files\/2021\/06\/unknown-15.png\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/blog.univ-angers.fr\/istiaprojetsei2\/files\/2021\/06\/unknown-15-150x150.png\" alt=\"\" width=\"150\" height=\"150\" class=\"alignnone size-thumbnail wp-image-1857\" \/><\/a><a href=\"https:\/\/blog.univ-angers.fr\/istiaprojetsei2\/files\/2021\/06\/unknown-16.png\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/blog.univ-angers.fr\/istiaprojetsei2\/files\/2021\/06\/unknown-16-150x150.png\" alt=\"\" width=\"150\" height=\"150\" class=\"alignnone size-thumbnail wp-image-1858\" \/><\/a><a href=\"https:\/\/blog.univ-angers.fr\/istiaprojetsei2\/files\/2021\/06\/unknown-17.png\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/blog.univ-angers.fr\/istiaprojetsei2\/files\/2021\/06\/unknown-17-150x150.png\" alt=\"\" width=\"150\" height=\"150\" class=\"alignnone size-thumbnail wp-image-1859\" \/><\/a><br \/>\n<em><br \/>\n1.3 Premiers essais <\/em><\/p>\n<p>Pour tester les branchements et le fonctionnement de l\u2019\u00e9cran OLED, voici un premier programme de test permettant d\u2019afficher \u00ab Hello, world ! \u00bb sur l\u2019\u00e9cran LCD :<br \/>\n<code><br \/>\n#include &lt;Arduino.h&gt;<br \/>\n#include &lt;U8g2lib.h&gt;<\/p>\n<p>#ifdef U8X8_HAVE_HW_SPI<br \/>\n#include &lt;SPI.h&gt;<br \/>\n#endif<br \/>\n#ifdef U8X8_HAVE_HW_I2C<br \/>\n#include &lt;Wire.h&gt;<br \/>\n#endif<\/p>\n<p>U8G2_SSD1306_128X64_NONAME_F_SW_I2C u8g2(U8G2_R0, \/* clock=*\/ SCL, \/* data=*\/ SDA, \/* reset=*\/ U8X8_PIN_NONE);<\/p>\n<p>void setup(void) {<br \/>\n  u8g2.begin();<br \/>\n}<br \/>\nvoid loop(void) {<br \/>\n  u8g2.clearBuffer();\t\t\t\t\t\/\/ clear the internal memory<br \/>\n  u8g2.setFont(u8g2_font_ncenB08_tr);\t\/\/ choose a suitable font<br \/>\n  u8g2.drawStr(0,10,\"Hello World!\");\t\/\/ write something to the internal memory<br \/>\n  u8g2.sendBuffer();\t\t\t\t\t\/\/ transfer internal memory to the display<br \/>\n  delay(1000);<br \/>\n}<br \/>\n<\/code><br \/>\n<a href=\"https:\/\/univangersfr-my.sharepoint.com\/:u:\/g\/personal\/aprat_etud_univ-angers_fr\/ERk6FkUU4odLtMzpF3jesDwBvSOu_Fs-sszVt4f8J3i6sg?e=kOtCXw\">https:\/\/univangersfr-my.sharepoint.com\/:u:\/g\/personal\/aprat_etud_univ-angers_fr\/ERk6FkUU4odLtMzpF3jesDwBvSOu_Fs-sszVt4f8J3i6sg?e=kOtCXw<\/a><\/p>\n<p>Voici maintenant un programme permettant de tester la lecture et l\u2019\u00e9criture sur une carte SD via le module carte SD :<br \/>\n<code><br \/>\n#include &lt;SPI.h&gt;<br \/>\n#include &lt;SD.h&gt;<\/p>\n<p>File myFile;<\/p>\n<p>void setup() {<br \/>\n  \/\/ Open serial communications and wait for port to open:<br \/>\n  Serial.begin(9600);<br \/>\n  while (!Serial) {<br \/>\n    ; \/\/ wait for serial port to connect. Needed for native USB port only<br \/>\n  }<\/p>\n<p>  Serial.print(\"Initializing SD card...\");<\/p>\n<p>  if (!SD.begin(4)) {<br \/>\n    Serial.println(\"initialization failed!\");<br \/>\n    while (1);<br \/>\n  }<br \/>\n  Serial.println(\"initialization done.\");<br \/>\n  \/\/ open the file. note that only one file can be open at a time,<br \/>\n  \/\/ so you have to close this one before opening another.<br \/>\n  myFile = SD.open(\"test.txt\", FILE_WRITE);<\/p>\n<p>  \/\/ if the file opened okay, write to it:<br \/>\n  if (myFile) {<br \/>\n    Serial.print(\"Writing to test.txt...\");<br \/>\n    myFile.println(\"testing 1, 2, 3.\");<br \/>\n    \/\/ close the file:<br \/>\n    myFile.close();<br \/>\n    Serial.println(\"done.\");<br \/>\n  } else {<br \/>\n    \/\/ if the file didn't open, print an error:<br \/>\n    Serial.println(\"error opening test.txt\");<br \/>\n  }<br \/>\n  \/\/ re-open the file for reading:<br \/>\n  myFile = SD.open(\"test.txt\");<br \/>\n  if (myFile) {<br \/>\n    Serial.println(\"test.txt:\");<\/p>\n<p>    \/\/ read from the file until there's nothing else in it:<br \/>\n    while (myFile.available()) {<br \/>\n      Serial.write(myFile.read());<br \/>\n    }<br \/>\n    \/\/ close the file:<br \/>\n    myFile.close();<br \/>\n  } else {<br \/>\n    \/\/ if the file didn't open, print an error:<br \/>\n    Serial.println(\"error opening test.txt\");<br \/>\n  }<br \/>\n}<br \/>\nvoid loop() {<br \/>\n  \/\/ nothing happens after setup<br \/>\n}<\/code><br \/>\n<a href=\"https:\/\/univangersfr-my.sharepoint.com\/:u:\/g\/personal\/aprat_etud_univ-angers_fr\/Ee6fWg755_1JvZVdp1jtcOoBkP_0hbTfrzpsgC0gugYstA?e=62gYhA\">https:\/\/univangersfr-my.sharepoint.com\/:u:\/g\/personal\/aprat_etud_univ-angers_fr\/Ee6fWg755_1JvZVdp1jtcOoBkP_0hbTfrzpsgC0gugYstA?e=62gYhA<\/a><\/p>\n<p>Ce programme va ainsi initialiser le module carte SD, il va \u00e9crire dans un fichier \u00ab test.txt \u00bb et le fermer, puis le rouvrir et afficher son contenu dans le moniteur s\u00e9rie.<br \/>\nVous pourrez ensuite retrouver ce fichier dans la carte SD en l\u2019ins\u00e9rant par exemple dans un ordinateur.<br \/>\n<strong><br \/>\n2\u00e8me \u00c9tape : Conversion des images !<\/strong><\/p>\n<p>Maintenant que nous avons install\u00e9 le mat\u00e9riel et test\u00e9 son bon fonctionnement, nous allons nous attaquer \u00e0 la deuxi\u00e8me dimension de ce projet : La conversion des images !<\/p>\n<p><em>2.1 Installation de Python et de la librairie Pil :<\/em><br \/>\nPour utiliser Python il va falloir l\u2019installer sur votre ordinateur, pour ce faire suivez ce lien de t\u00e9l\u00e9chargement :<br \/>\n<a href=\"https:\/\/www.python.org\/downloads\/\">https:\/\/www.python.org\/downloads\/<\/a><\/p>\n<p>Une fois Python install\u00e9 sur votre ordinateur, vous aurez acc\u00e8s \u00e0 la console Python et vous pourrez \u00e9crire des programme Python \u00e0 l\u2019aide d\u2019un \u00e9diteur de texte pour l\u2019ex\u00e9cuter par la suite.<br \/>\nPour ma part, j\u2019ai utilis\u00e9 le logiciel Visual Studio Code pour programmer et ex\u00e9cuter mes programmes Pythons, je vais donc vous expliquer comment le param\u00e9trer.<br \/>\nPour commencer voici o\u00f9 le t\u00e9l\u00e9charger :<br \/>\n<a href=\"https:\/\/code.visualstudio.com\/Download\">https:\/\/code.visualstudio.com\/Download<\/a><br \/>\nUne fois install\u00e9, voici \u00e0 quoi ressemble VSCode :<br \/>\n<a href=\"https:\/\/blog.univ-angers.fr\/istiaprojetsei2\/files\/2021\/06\/unknown-18.png\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/blog.univ-angers.fr\/istiaprojetsei2\/files\/2021\/06\/unknown-18-300x156.png\" alt=\"\" width=\"300\" height=\"156\" class=\"alignnone size-medium wp-image-1861\" srcset=\"https:\/\/blog.univ-angers.fr\/polytech_2A\/files\/2021\/06\/unknown-18-300x156.png 300w, https:\/\/blog.univ-angers.fr\/polytech_2A\/files\/2021\/06\/unknown-18-500x261.png 500w, https:\/\/blog.univ-angers.fr\/polytech_2A\/files\/2021\/06\/unknown-18.png 605w\" sizes=\"auto, (max-width: 300px) 100vw, 300px\" \/><\/a><br \/>\nVous pourrez ensuite cliquer sur l\u2019onglet extension et taper Python dans la barre de recherche :<br \/>\n<a href=\"https:\/\/blog.univ-angers.fr\/istiaprojetsei2\/files\/2021\/06\/unknown-19.png\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/blog.univ-angers.fr\/istiaprojetsei2\/files\/2021\/06\/unknown-19-300x158.png\" alt=\"\" width=\"300\" height=\"158\" class=\"alignnone size-medium wp-image-1862\" srcset=\"https:\/\/blog.univ-angers.fr\/polytech_2A\/files\/2021\/06\/unknown-19-300x158.png 300w, https:\/\/blog.univ-angers.fr\/polytech_2A\/files\/2021\/06\/unknown-19-500x264.png 500w, https:\/\/blog.univ-angers.fr\/polytech_2A\/files\/2021\/06\/unknown-19.png 605w\" sizes=\"auto, (max-width: 300px) 100vw, 300px\" \/><\/a><br \/>\n\u00c0 la place de disable et uninstall vous pourrez cliquer sur install pour installer l\u2019extension.<br \/>\nVous pourrez taper Pylance dans la barre de recherche et l\u2019installer de la m\u00eame mani\u00e8re :<br \/>\n<a href=\"https:\/\/blog.univ-angers.fr\/istiaprojetsei2\/files\/2021\/06\/unknown-20.png\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/blog.univ-angers.fr\/istiaprojetsei2\/files\/2021\/06\/unknown-20-300x158.png\" alt=\"\" width=\"300\" height=\"158\" class=\"alignnone size-medium wp-image-1865\" srcset=\"https:\/\/blog.univ-angers.fr\/polytech_2A\/files\/2021\/06\/unknown-20-300x158.png 300w, https:\/\/blog.univ-angers.fr\/polytech_2A\/files\/2021\/06\/unknown-20-500x264.png 500w, https:\/\/blog.univ-angers.fr\/polytech_2A\/files\/2021\/06\/unknown-20.png 605w\" sizes=\"auto, (max-width: 300px) 100vw, 300px\" \/><\/a><br \/>\nUne fois les deux extensions install\u00e9es, vous pourrez ouvrir le fichier de test \u00ab Hello world.py \u00bb ci-dessous :<br \/>\n<a href=\"https:\/\/univangersfr-my.sharepoint.com\/:u:\/g\/personal\/aprat_etud_univ-angers_fr\/EVWGSzy1pilHsRCo0CzoPqcBlutOLND8Hc4icxtwV6BVIA?e=TTEPhC\">https:\/\/univangersfr-my.sharepoint.com\/:u:\/g\/personal\/aprat_etud_univ-angers_fr\/EVWGSzy1pilHsRCo0CzoPqcBlutOLND8Hc4icxtwV6BVIA?e=TTEPhC<\/a><\/p>\n<p>Une fois le fichier ouvert, vous pourrez cliquer en bas \u00e0 gauche et s\u00e9lectionner l\u2019interpr\u00e9teur python si cela n\u2019est pas d\u00e9j\u00e0 fait.<br \/>\n<a href=\"https:\/\/blog.univ-angers.fr\/istiaprojetsei2\/files\/2021\/06\/unknown-21.png\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/blog.univ-angers.fr\/istiaprojetsei2\/files\/2021\/06\/unknown-21-300x162.png\" alt=\"\" width=\"300\" height=\"162\" class=\"alignnone size-medium wp-image-1866\" srcset=\"https:\/\/blog.univ-angers.fr\/polytech_2A\/files\/2021\/06\/unknown-21-300x162.png 300w, https:\/\/blog.univ-angers.fr\/polytech_2A\/files\/2021\/06\/unknown-21-500x270.png 500w, https:\/\/blog.univ-angers.fr\/polytech_2A\/files\/2021\/06\/unknown-21.png 605w\" sizes=\"auto, (max-width: 300px) 100vw, 300px\" \/><\/a><br \/>\nVous pourrez ensuite appuyer sur F5 et cliquer sur \u00ab Python File \u00bb pour ex\u00e9cuter le programme Python.<br \/>\n<a href=\"https:\/\/blog.univ-angers.fr\/istiaprojetsei2\/files\/2021\/06\/unknown-22.png\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/blog.univ-angers.fr\/istiaprojetsei2\/files\/2021\/06\/unknown-22-300x162.png\" alt=\"\" width=\"300\" height=\"162\" class=\"alignnone size-medium wp-image-1867\" srcset=\"https:\/\/blog.univ-angers.fr\/polytech_2A\/files\/2021\/06\/unknown-22-300x162.png 300w, https:\/\/blog.univ-angers.fr\/polytech_2A\/files\/2021\/06\/unknown-22-500x271.png 500w, https:\/\/blog.univ-angers.fr\/polytech_2A\/files\/2021\/06\/unknown-22.png 605w\" sizes=\"auto, (max-width: 300px) 100vw, 300px\" \/><\/a><br \/>\nUne fois ex\u00e9cut\u00e9 celui-ci devrait afficher \u00ab Hello world \u00bb dans le terminal Python en bas de la page.<br \/>\nAttention ! Pensez \u00e0 bien v\u00e9rifier que le terminal s\u00e9lectionn\u00e9 est bien le terminal Python :<br \/>\n<a href=\"https:\/\/blog.univ-angers.fr\/istiaprojetsei2\/files\/2021\/06\/unknown-23.png\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/blog.univ-angers.fr\/istiaprojetsei2\/files\/2021\/06\/unknown-23-300x162.png\" alt=\"\" width=\"300\" height=\"162\" class=\"alignnone size-medium wp-image-1868\" srcset=\"https:\/\/blog.univ-angers.fr\/polytech_2A\/files\/2021\/06\/unknown-23-300x162.png 300w, https:\/\/blog.univ-angers.fr\/polytech_2A\/files\/2021\/06\/unknown-23-500x270.png 500w, https:\/\/blog.univ-angers.fr\/polytech_2A\/files\/2021\/06\/unknown-23.png 605w\" sizes=\"auto, (max-width: 300px) 100vw, 300px\" \/><\/a><br \/>\nEnsuite une fois dans le terminal Python, vous pourrez taper \u00ab pip install Pillow \u00bb afin d\u2019installer la librairie PIL :<br \/>\n<a href=\"https:\/\/blog.univ-angers.fr\/istiaprojetsei2\/files\/2021\/06\/unknown-24.png\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/blog.univ-angers.fr\/istiaprojetsei2\/files\/2021\/06\/unknown-24-300x162.png\" alt=\"\" width=\"300\" height=\"162\" class=\"alignnone size-medium wp-image-1869\" srcset=\"https:\/\/blog.univ-angers.fr\/polytech_2A\/files\/2021\/06\/unknown-24-300x162.png 300w, https:\/\/blog.univ-angers.fr\/polytech_2A\/files\/2021\/06\/unknown-24-500x271.png 500w, https:\/\/blog.univ-angers.fr\/polytech_2A\/files\/2021\/06\/unknown-24.png 605w\" sizes=\"auto, (max-width: 300px) 100vw, 300px\" \/><\/a><br \/>\nSi tout s\u2019est bien pass\u00e9, la librairie PIL est bien install\u00e9e et Python est pr\u00eat \u00e0 \u00eatre utilis\u00e9 !<\/p>\n<p><em>2.2 Programme Python<\/em><\/p>\n<p>Pour convertir des images classiques en images monochromes 128&#215;64 puis en matrices binaires texte, nous utilisons un programme Python.<br \/>\nVoici le programme Python en question :<br \/>\n<code><br \/>\nfrom PIL import Image<br \/>\nimport os<br \/>\nfilename=input(\"Quelle image souhaites-tu convertir ? (nom.extension)\")<br \/>\nwith Image.open(filename) as image:<br \/>\n    if image.width somme):<br \/>\n                pixels_converted[x,y]=1<br \/>\n            else:<br \/>\n                pixels_converted[x,y]=0<br \/>\n    for x in range(width):<br \/>\n            if(pixels_converted[x,y]==1 or pixels_converted[x,y]==0):<br \/>\n                i+=1   <\/p>\n<p>converted_image.show()<br \/>\nmatrice = converted_image.load()<\/p>\n<p>with open(\"code.txt\", \"w\") as file:<\/p>\n<p>    for i in range(height):<br \/>\n        for j in range(width):<br \/>\n            if matrice[j, i] &gt; 0:<br \/>\n                file.write(\"1\")<br \/>\n            else:<br \/>\n                file.write(\"0\")<\/code><br \/>\n<a href=\"https:\/\/univangersfr-my.sharepoint.com\/:u:\/g\/personal\/aprat_etud_univ-angers_fr\/EWBx62pzzhpMgB6UHysoCksBieBGAg5BUCkhj9wa-sThKQ?e=hwkbk8\">https:\/\/univangersfr-my.sharepoint.com\/:u:\/g\/personal\/aprat_etud_univ-angers_fr\/EWBx62pzzhpMgB6UHysoCksBieBGAg5BUCkhj9wa-sThKQ?e=hwkbk8<\/a><\/p>\n<p>Il vous suffit ainsi de t\u00e9l\u00e9charger une image, de la d\u00e9poser dans le m\u00eame dossier que le programme Python, d\u2019ex\u00e9cuter le programme Python, d\u2019entrer le nom et l\u2019extension de l\u2019image quand le programme vous la demande (nom.extension), et le programme cr\u00e9era un fichier image.txt contenant une matrice de 0 et de 1 correspondant aux pixels de l\u2019image. Fichier texte qui pourra \u00eatre interpr\u00e9t\u00e9 par l\u2019ESP32 pour l\u2019affichage de l\u2019image sur l\u2019\u00e9cran OLED.\t<\/p>\n<p>Ainsi ce programme ouvre l\u2019image, v\u00e9rifie s\u2019il s\u2019agit d\u2019une image portrait ou paysage, en cas de portrait il la retourne en paysage, il la redimensionne en 128&#215;64, la convertie en noir et blanc puis en monochrome, puis \u00e9cris chaque pixel dans une matrice binaire dans un fichier texte.<br \/>\n<strong><br \/>\n3\u00e8me \u00c9tape : Tester l\u2019application finale !<\/strong><\/p>\n<p>Maintenant l\u2019installation faite, les composants fonctionnels et une image de converti, il nous reste plus qu\u2019\u00e0 tester notre application finale !<br \/>\nPour commencer vous allez pouvoir glisser le fichier image.txt fournis par le programme Python dans le r\u00e9pertoire principal d\u2019une carte SD, et ins\u00e9rer cette m\u00eame carte SD dans le module carte SD branch\u00e9 \u00e0 l\u2019ESP32.<br \/>\nVoici ensuite le programme permettant de lire, g\u00e9r\u00e9 et afficher l\u2019image sur l\u2019\u00e9cran OLED via l\u2019ESP32 :<br \/>\n<code>#include &lt;Arduino.h&gt;<br \/>\n#include &lt;U8g2lib.h&gt;<br \/>\n#include &lt;SPI.h&gt;<br \/>\n#include &lt;SD.h&gt;<\/p>\n<p>#ifdef U8X8_HAVE_HW_I2C<br \/>\n#include &lt;Wire.h&gt;<br \/>\n#endif<\/p>\n<p>\/\/On renseigne notre \u00e9cran pour la librairie U8g2<br \/>\nU8G2_SSD1306_128X64_NONAME_F_SW_I2C u8g2(U8G2_R0, \/* clock=*\/ SCL, \/* data=*\/ SDA, \/* reset=*\/ U8X8_PIN_NONE);<\/p>\n<p>byte image[8192];     \/\/tableau stockant chaque bit correspondant \u00e0 chaque pixel (converti en byte)<br \/>\nchar tabCode[8192];   \/\/tableau stockant chaque bit correspondant \u00e0 chaque pixel (obtenu en char dans la carte SD)<br \/>\nint octet, len, i, j;<\/p>\n<p>void setup(void) {<br \/>\n  pinMode(10, OUTPUT);<br \/>\n  pinMode(9, OUTPUT);<\/p>\n<p>  digitalWrite(10, 0);<br \/>\n  digitalWrite(9, 0);\t\t<\/p>\n<p>  \/\/Initialisation de l'\u00e9cran OLED<br \/>\n  u8g2.begin();<br \/>\n  u8g2.enableUTF8Print();<br \/>\n  \/\/On s\u00e9lectionne une police<br \/>\n  u8g2.setFont(u8g2_font_ncenB08_tr);<\/p>\n<p>  \/\/initialisation du moniteur s\u00e9rie<br \/>\n  Serial.begin(115200);<\/p>\n<p>  \/\/On v\u00e9rifie si la carte SD est d\u00e9tect\u00e9e, si ce n'est pas le cas, on affiche un message d'erreur sur l'\u00e9cran OLED<br \/>\n  if(!SD.begin()){<br \/>\n    u8g2.drawStr(0,10,\"La carte ne fonctionne\");<br \/>\n    u8g2.drawStr(0,30,\"pas !\");<br \/>\n    u8g2.sendBuffer();<br \/>\n    u8g2.clearBuffer();<br \/>\n    delay(1000);<br \/>\n    return;<br \/>\n  }<\/p>\n<p>  \/\/On ouvre le fichier image.txt dans la carte SD<br \/>\n  File file = SD.open(\"\/image.txt\");<br \/>\n  \/\/Si le fichier est introuvable, on affiche un message d'erreur sur l'\u00e9cran OLED<br \/>\n  if(!file){<br \/>\n    u8g2.drawStr(0,10,\"Impossible d'ouvrir\");<br \/>\n    u8g2.drawStr(0,30,\"image.txt\");<br \/>\n    u8g2.sendBuffer();<br \/>\n    u8g2.clearBuffer();<br \/>\n    return;<br \/>\n  }<\/p>\n<p>  \/\/Tant que l'on a pas parcouru enti\u00e8rement le fichier image.txt, on sauvegarde chaque pixel (0 ou 1) dans le tableau tabChar<br \/>\n  i=0;<br \/>\n  while(file.available()){<br \/>\n    tabCode[i] = char(file.read());<br \/>\n    i++;<br \/>\n  }<br \/>\n  file.close();   \/\/Une fois fait, on ferme le fichier<\/p>\n<p>  \/\/Nous parcourons ensuite chaque case du tableau tabChar pour le convertir en byte au lieu de char dans le tableau image<br \/>\n  for(i=0; i&lt;8192; i++) {<br \/>\n    if(tabCode[i] == &#039;0&#039;) {<br \/>\n      image[i] = 0;<br \/>\n    } else {<br \/>\n      image[i] = 1;<br \/>\n    }<br \/>\n  }<\/p>\n<p>  for(i=0; i&lt;128; i++) {          \/\/boucle for permettant de parcours l'axe i<br \/>\n    for(j=0; j&lt;64; j++) {         \/\/boucle for permettant de parcours l'axe j<br \/>\n      \/\/octet stock la valeur 0 ou 1 de chaque pixel<br \/>\n      \/\/pgm_read_byte_near lit dans la PROGMEM \u00e0 l'adresse<br \/>\n      \/\/image (pixel initial de l'image) + j*128+i (auquel on ajoute les pixel d\u00e9j\u00e0 parcourus)<br \/>\n      octet = pgm_read_byte_near(image + j*128+i);<br \/>\n      if (octet &gt;= 1) {<br \/>\n        u8g2.drawPixel(i,j);      \/\/Si octet = 1, nous dessinons un pixel aux coordonn\u00e9es (i,j)<br \/>\n      }<br \/>\n    }<br \/>\n  }<br \/>\n  u8g2.sendBuffer();              \/\/Nous envoyons le buffer pour afficher l'image<br \/>\n}<br \/>\nvoid loop(void) {}<\/code><\/p>\n<p><a href=\"https:\/\/univangersfr-my.sharepoint.com\/:u:\/g\/personal\/aprat_etud_univ-angers_fr\/ERTFzhOP7HtPlpy8cJ-IyqoBxnxTRO1hpxFi83kHeW0Bkw?e=sdvdc5\">https:\/\/univangersfr-my.sharepoint.com\/:u:\/g\/personal\/aprat_etud_univ-angers_fr\/ERTFzhOP7HtPlpy8cJ-IyqoBxnxTRO1hpxFi83kHeW0Bkw?e=sdvdc5<\/a><\/p>\n<p>Vous pourrez ainsi compiler et t\u00e9l\u00e9verser ce programme sur l\u2019ESP32 afin de le faire fonctionner.<br \/>\nEn cas de non-d\u00e9tection ou d\u2019absence de carte SD, le programme affichera des messages d\u2019erreurs sur l\u2019\u00e9cran OLED.<br \/>\n<a href=\"https:\/\/blog.univ-angers.fr\/istiaprojetsei2\/files\/2021\/06\/unknown-26.png\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/blog.univ-angers.fr\/istiaprojetsei2\/files\/2021\/06\/unknown-26.png\" alt=\"\" width=\"300\" height=\"159\" class=\"alignnone size-full wp-image-1871\" \/><\/a><\/p>\n<p>Il est \u00e9galement bon \u00e0 savoir qu\u2019une simple carte Arduino aurait aussi pu \u00eatre utilis\u00e9e pour cette partie car sa m\u00e9moire est suffisante pour afficher une simple image.<br \/>\nDans ce cas le programme aurait \u00e9t\u00e9 le m\u00eame, la seule diff\u00e9rence aurait \u00e9t\u00e9 le branchement du module carte SD et de l\u2019\u00e9cran OLED.<br \/>\n<div id=\"attachment_1872\" style=\"width: 310px\" class=\"wp-caption alignnone\"><a href=\"https:\/\/blog.univ-angers.fr\/istiaprojetsei2\/files\/2021\/06\/unknown-27.png\"><img loading=\"lazy\" decoding=\"async\" aria-describedby=\"caption-attachment-1872\" src=\"https:\/\/blog.univ-angers.fr\/istiaprojetsei2\/files\/2021\/06\/unknown-27-300x186.png\" alt=\"GND -&gt; GND VCC -&gt; +5V SDA -&gt; A4 SCL -&gt; A5 \" width=\"300\" height=\"186\" class=\"size-medium wp-image-1872\" srcset=\"https:\/\/blog.univ-angers.fr\/polytech_2A\/files\/2021\/06\/unknown-27-300x186.png 300w, https:\/\/blog.univ-angers.fr\/polytech_2A\/files\/2021\/06\/unknown-27.png 355w\" sizes=\"auto, (max-width: 300px) 100vw, 300px\" \/><\/a><p id=\"caption-attachment-1872\" class=\"wp-caption-text\">\u00c9cran OLED<br \/>GND -&gt; GND<br \/><font color=\"red\">VCC -&gt; +5V<br \/><\/font><font color=\"orange\">SDA -&gt; A4<br \/><\/font><font color=\"blue\">SCL -&gt; A5<br \/><\/font><\/p><\/div><\/p>\n<p><strong>3.2\u00b0 Gif avec ESP32 :<\/strong><\/p>\n<p><strong>1\u00e8re \u00c9tape : Pr\u00e9paration <\/strong><br \/>\nPour cette premi\u00e8re partie de pr\u00e9paration, je vous invite \u00e0 vous r\u00e9f\u00e9rer \u00e0 la partie Pr\u00e9paration du 3.1\u00b0 Image avec ESP32 et carte SD.<br \/>\n(Vous pourrez cependant omettre la partie sur le module carte SD car celui-ci ne sera pas utilis\u00e9 dans cette partie)<\/p>\n<p><strong>2\u00e8me \u00c9tape : Conversion des GIF !<\/strong><br \/>\nDans cette partie, nous allons \u00e0 nouveau utiliser un programme Python, je vous invite donc \u00e0 vous r\u00e9f\u00e9rer \u00e0 la partie Conversion des images du 3.1\u00b0 Image avec ESP32 et carte SD pour configurer votre environnement Python.<br \/>\nVoici ainsi le programme Python que nous allons utiliser :<br \/>\n<code><br \/>\nfrom PIL import Image<br \/>\nfilename=input(\"Quel est le nom de votre fichier ? \")<br \/>\ntaille=int(input(\"Combien d'images contient votre GIF ? \"))<br \/>\next=input(\"Quel est le format de vos images ? \")<br \/>\nwith open(\".\/\"+ filename + \"\/\" + filename + \".txt\", \"w\") as file:<br \/>\n    file.write(\"const byte image[FRAME][8192] PROGMEM = {\")<br \/>\n    for k in range(1,taille+1):<br \/>\n        file.write(\"{\")<br \/>\n        with Image.open(\".\/\"+ filename + \"\/\" + filename + \" (\" + str(k) + \").\" + ext) as image:<br \/>\n            if image.width somme):<br \/>\n                        pixels_converted[x,y]=1<br \/>\n                    else:<br \/>\n                        pixels_converted[x,y]=0<br \/>\n            for x in range(width):<br \/>\n                    if(pixels_converted[x,y]==1 or pixels_converted[x,y]==0):<br \/>\n                        i+=1   <\/p>\n<p>        converted_image.show()<br \/>\n        matrice = converted_image.load()<\/p>\n<p>        for i in range(height):<br \/>\n            for j in range(width):<br \/>\n                if matrice[j, i] &gt; 0:<br \/>\n                    file.write(\"1\")<br \/>\n                    if i != height-1 or j != width-1:<br \/>\n                        file.write(\", \")<br \/>\n                else:<br \/>\n                    file.write(\"0\")<br \/>\n                    if i != height-1 or j != width-1:<br \/>\n                        file.write(\", \")<br \/>\n        file.write(\"}\")<br \/>\n        if k != taille:<br \/>\n            file.write(\",\")<br \/>\n    file.write(\"};\")<\/code><br \/>\n<a href=\"https:\/\/univangersfr-my.sharepoint.com\/:u:\/g\/personal\/aprat_etud_univ-angers_fr\/EfVCE6Hw3ytBnuYc3vhnvFEBFCePw2eylysbpYSbD7Pokw?e=UzuEFV\">https:\/\/univangersfr-my.sharepoint.com\/:u:\/g\/personal\/aprat_etud_univ-angers_fr\/EfVCE6Hw3ytBnuYc3vhnvFEBFCePw2eylysbpYSbD7Pokw?e=UzuEFV<\/a><\/p>\n<p>Pour fonctionner, notre programme Python a besoin d\u2019un dossier contenant chaque \u00ab frames \u00bb du GIF souhaitant \u00eatre affich\u00e9.<br \/>\nPour convertir notre GIF en archives ZIP contenant chaque \u00ab frames \u00bb de notre GIF, je vous propose l\u2019utilisation de ce site tiers : <a href=\"https:\/\/ezgif.com\/split\">https:\/\/ezgif.com\/split<\/a><br \/>\nDans notre exemple, nous utiliserons ce GIF :<a href=\"https:\/\/tenor.com\/view\/yay-yes-yeahhh-cute-girl-happy-dance-gif-14559695\">https:\/\/tenor.com\/view\/yay-yes-yeahhh-cute-girl-happy-dance-gif-14559695<\/a><\/p>\n<p>Il vous suffit ainsi d\u2019uploader votre GIF sur le site ou d\u2019y d\u00e9poser un lien, puis de cliquer sur Upload :<br \/>\n<a href=\"https:\/\/blog.univ-angers.fr\/istiaprojetsei2\/files\/2021\/06\/unknown-28.png\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/blog.univ-angers.fr\/istiaprojetsei2\/files\/2021\/06\/unknown-28-300x155.png\" alt=\"\" width=\"300\" height=\"155\" class=\"alignnone size-medium wp-image-1873\" srcset=\"https:\/\/blog.univ-angers.fr\/polytech_2A\/files\/2021\/06\/unknown-28-300x155.png 300w, https:\/\/blog.univ-angers.fr\/polytech_2A\/files\/2021\/06\/unknown-28.png 416w\" sizes=\"auto, (max-width: 300px) 100vw, 300px\" \/><\/a><br \/>\nIl ne vous restera plus qu\u2019\u00e0 cliquer sur Split to frames et la magie op\u00e8rera.<br \/>\nVous n\u2019aurez plus qu\u2019\u00e0 cliquer sur Download frames as ZIP : <a href=\"https:\/\/blog.univ-angers.fr\/istiaprojetsei2\/files\/2021\/06\/unknown-30.png\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/blog.univ-angers.fr\/istiaprojetsei2\/files\/2021\/06\/unknown-30.png\" alt=\"\" width=\"294\" height=\"112\" class=\"alignnone size-full wp-image-1874\" \/><\/a><\/p>\n<p>Vous vous retrouverez ainsi avec une archive ZIP contenant toutes vos frames :<br \/>\n<a href=\"https:\/\/blog.univ-angers.fr\/istiaprojetsei2\/files\/2021\/06\/unknown-31.png\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/blog.univ-angers.fr\/istiaprojetsei2\/files\/2021\/06\/unknown-31-300x150.png\" alt=\"\" width=\"300\" height=\"150\" class=\"alignnone size-medium wp-image-1875\" srcset=\"https:\/\/blog.univ-angers.fr\/polytech_2A\/files\/2021\/06\/unknown-31-300x150.png 300w, https:\/\/blog.univ-angers.fr\/polytech_2A\/files\/2021\/06\/unknown-31-500x250.png 500w, https:\/\/blog.univ-angers.fr\/polytech_2A\/files\/2021\/06\/unknown-31.png 605w\" sizes=\"auto, (max-width: 300px) 100vw, 300px\" \/><\/a><br \/>\nVous pourrez ensuite cr\u00e9er un dossier du nom de votre GIF (que vous pouvez choisir), dans notre cas nous l\u2019appellerons \u00ab girl \u00bb, et y glisser toutes les images.<br \/>\nUne fois les images dans le dossier, s\u00e9lectionner toutes les images, faites clique-droit sur la premi\u00e8re image (tout en gardant toutes les images s\u00e9lectionn\u00e9es), appuyez sur renommer et entrez le nom de votre GIF (Attention cela doit \u00eatre le m\u00eame nom que celui du dossier !)<br \/>\nAinsi, toutes les images vont \u00eatre renomm\u00e9es en \u00ab nom (x) \u00bb :<br \/>\n<a href=\"https:\/\/blog.univ-angers.fr\/istiaprojetsei2\/files\/2021\/06\/unknown-34.png\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/blog.univ-angers.fr\/istiaprojetsei2\/files\/2021\/06\/unknown-34-291x300.png\" alt=\"\" width=\"291\" height=\"300\" class=\"alignnone size-medium wp-image-1876\" srcset=\"https:\/\/blog.univ-angers.fr\/polytech_2A\/files\/2021\/06\/unknown-34-291x300.png 291w, https:\/\/blog.univ-angers.fr\/polytech_2A\/files\/2021\/06\/unknown-34.png 299w\" sizes=\"auto, (max-width: 291px) 100vw, 291px\" \/><\/a><br \/>\nIl ne vous reste plus qu\u2019\u00e0 d\u00e9placer ce dossier dans le r\u00e9pertoire du programme Python !<br \/>\nIl ne vous reste plus qu\u2019\u00e0 ex\u00e9cuter le programme Python, d\u2019entrer le nom de votre GIF (nom du dossier), d\u2019entrer le nombre d\u2019images que contient le GIF (dans notre exemple 28) et pour finir d\u2019entrer le format de nos images (dans notre cas .gif).<br \/>\nUne fois le programme ex\u00e9cut\u00e9, vous trouverez un fichier texte portant le nom de votre GIF \u00e0 l\u2019int\u00e9rieur du dossier contenant les images du GIF.<\/p>\n<p><strong>3\u00e8me \u00c9tape : Tester l\u2019application finale !<\/strong><\/p>\n<p>Maintenant l\u2019installation faite, les composants fonctionnels et un GIF de converti, il nous reste plus qu\u2019\u00e0 tester notre application finale !<br \/>\nPour commencer vous allez pouvoir ouvrir le fichier texte contenant le GIF, tout s\u00e9lectionner (CTRL+A) et tout copier (CTRL+C).<br \/>\nVoici ensuite le programme permettant de lire, g\u00e9r\u00e9 et afficher le GIF sur l\u2019\u00e9cran OLED via l\u2019ESP32 :<br \/>\n<code>#include &lt;Arduino.h&gt;<br \/>\n#include &lt;U8g2lib.h&gt;<\/p>\n<p>#ifdef U8X8_HAVE_HW_SPI<br \/>\n#include &lt;SPI.h&gt;<br \/>\n#endif<br \/>\n#ifdef U8X8_HAVE_HW_I2C<br \/>\n#include &lt;Wire.h&gt;<br \/>\n#endif<\/p>\n<p>#define FRAME 24 \/\/N'oubliez pas de renseigner le nombre d'images ICI<\/p>\n<p>\/\/On renseigne notre \u00e9cran pour la librairie U8g2<br \/>\nU8G2_SSD1306_128X64_NONAME_F_SW_I2C u8g2(U8G2_R0, \/* clock=*\/ SCL, \/* data=*\/ SDA, \/* reset=*\/ U8X8_PIN_NONE);<\/p>\n<p>\/\/COLLEZ LE CONTENU DU FICHIER TEXTE ICI<br \/>\nint tmp, octet;<\/p>\n<p>void setup(void) {<br \/>\n  pinMode(10, OUTPUT);<br \/>\n  pinMode(9, OUTPUT);<\/p>\n<p>  digitalWrite(10, 0);<br \/>\n  digitalWrite(9, 0);<\/p>\n<p>  \/\/Initialisation de l'\u00e9cran OLED<br \/>\n  u8g2.begin();<br \/>\n  u8g2.enableUTF8Print();<\/p>\n<p>  \/\/Initialisation de l'\u00e9cran LCD<br \/>\n  Serial.begin(115200);<br \/>\n}<\/p>\n<p>\/\/Important ! Nous utilisons un tableau \u00e0 deux dimension pour stocker chaque image du GIF, nous avons ainsi un tableau de dimension [nb images][r\u00e9solution image]<br \/>\nvoid loop(void) {<br \/>\n  tmp = 0;                              \/\/Cette variable permet de savoir \u00e0 quelle image du GIF nous sommes rendu<br \/>\n  for(int k=0; k&lt;FRAME; k++){           \/\/boucle for permettant de parcours chaque image<br \/>\n    for(int i=0; i&gt;128; i++) {          \/\/boucle for permettant de parcours l&#039;axe i<br \/>\n      for(int j=0; j&gt;64; j++) {         \/\/boucle for permettant de parcours l&#039;axe j<br \/>\n        \/\/octet stock la valeur 0 ou 1 de chaque pixel<br \/>\n        \/\/pgm_read_byte_near lit dans la PROGMEM \u00e0 l&#039;adresse<br \/>\n        \/\/&amp;image[tmp][0] (pixel initial de l&#039;image) + j*128+i (auquel on ajoute les pixel d\u00e9j\u00e0 parcourus)<br \/>\n        octet = pgm_read_byte_near(&amp;image[tmp][0] + j*128+i);<br \/>\n        if (octet &lt;= 1) {<br \/>\n          u8g2.drawPixel(i,j);           \/\/Si octet = 1, nous dessinons un pixel aux coordonn\u00e9es (i,j)<br \/>\n       }}}<br \/>\n    tmp++;                \/\/Une fois une image termin\u00e9e, nous incr\u00e9mentons tmp<br \/>\n    u8g2.sendBuffer();    \/\/Nous envoyons le buffer pour afficher l&#039;image<br \/>\n    delay(20);            \/\/Nous attendons afin de voir passer chaque image avec un taux de rafraichissement assez \u00e9lev\u00e9<br \/>\n    u8g2.clearBuffer();   \/\/Nous vidons le buffer pour traiter la prochaine image<br \/>\n  }}<br \/>\n<\/code><br \/>\n<a href=\"https:\/\/univangersfr-my.sharepoint.com\/:u:\/g\/personal\/aprat_etud_univ-angers_fr\/Ec2G1Tw-84ZJjZ-lkY_vkNMBc1qo9AIru2uRP_ii-V2hNw?e=ny844n\">https:\/\/univangersfr-my.sharepoint.com\/:u:\/g\/personal\/aprat_etud_univ-angers_fr\/Ec2G1Tw-84ZJjZ-lkY_vkNMBc1qo9AIru2uRP_ii-V2hNw?e=ny844n<\/a><\/p>\n<p>Pour faire fonctionner ce programme, il ne vous reste plus que 2 choses \u00e0 faire, tout d\u2019abord, renseignez le nombre d\u2019images que contient votre GIF ligne 11, et ensuite, collez (CTRL+V) le contenu du fichier texte que nous avons pr\u00e9alablement copi\u00e9 ligne 15 ! (V\u00e9rifiez bien que le contenu de la ligne 16 ne s\u2019est pas gliss\u00e9e \u00e0 la fin de la ligne 15, m\u00eame si cela ne devrait pas poser de probl\u00e8mes).<br \/>\nUne fois fait, vous pouvez t\u00e9l\u00e9verser le programme dans l\u2019ESP32 et le GIF anim\u00e9 s\u2019affichera sur l\u2019\u00e9cran OLED.<\/p>\n<p>J\u2019ai \u00e9galement voulu adapter ce programme de lecture de GIF au module carte SD mais une erreur et un manque de temps a fait que je n\u2019ai pas pu terminer l\u2019impl\u00e9mentation de cette fonction.<br \/>\nVoici cependant le lien vers le programme Arduino permettant en th\u00e9orie de lire le GIF depuis la carte SD, mais qui dans mon cas ne fonctionnait pas :<br \/>\n<a href=\"https:\/\/univangersfr-my.sharepoint.com\/:u:\/g\/personal\/aprat_etud_univ-angers_fr\/EYEKnGtNrkhMpeXnzJrRPr8BBACLnJAxCUyLtusdikfvIA?e=iLYBPD\">https:\/\/univangersfr-my.sharepoint.com\/:u:\/g\/personal\/aprat_etud_univ-angers_fr\/EYEKnGtNrkhMpeXnzJrRPr8BBACLnJAxCUyLtusdikfvIA?e=iLYBPD<\/a><br \/>\nPour utiliser ce programme, il vous faudra l\u00e9g\u00e8rement modifier le programme Gif Convertor.py, il vous faudra en effet commenter le lignes 6, 8, 41, 42, 45, 46, 47, 48, 49, 50.<br \/>\nLe programme Python vous cr\u00e9era ainsi toujours un fichier texte que vous renommerez gif.txt, et que vous glisserez dans la carte SD.<br \/>\nEn th\u00e9orie cette m\u00e9thode est sens\u00e9e fonctionner mais je n\u2019ai pas r\u00e9ussi \u00e0 la mener \u00e0 bien.<\/p>\n<p><strong><font color=\"red\">Projet n\u00b04 : Allumage d\u2019un \u00e9cran LCD par proximit\u00e9 &#8211; R\u00e9alis\u00e9 par Zacharie FOURRIER <\/strong><\/font><\/p>\n<p>Mot cl\u00e9 : ESP32 , \u00e9cran LCD , Arduino, AppInventor<\/p>\n<p><strong>1\u00e8re \u00e9tape : Pr\u00e9paration<\/strong><br \/>\n<em>1.1\tMat\u00e9riel<\/em><br \/>\n1x ESP32<br \/>\n1x Ecran LCD<br \/>\n1x Adaptateur I2C pour l\u2019\u00e9cran LCD<br \/>\n+ fils et backplate<\/p>\n<p><em>1.2 Librairies Arduino<br \/>\n<\/em><br \/>\n&#8211; <strong>BluetoothSerial<\/strong> (Bluetooth est pr\u00e9install\u00e9e dans l\u2019IDE Arduino)<br \/>\n&#8211; LiquidCrystal_I2C version 1.1.2<br \/>\n<a href=\"https:\/\/blog.univ-angers.fr\/istiaprojetsei2\/files\/2021\/06\/unknown-36.png\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/blog.univ-angers.fr\/istiaprojetsei2\/files\/2021\/06\/unknown-36.png\" alt=\"\" width=\"605\" height=\"96\" class=\"alignnone size-full wp-image-1885\" srcset=\"https:\/\/blog.univ-angers.fr\/polytech_2A\/files\/2021\/06\/unknown-36.png 605w, https:\/\/blog.univ-angers.fr\/polytech_2A\/files\/2021\/06\/unknown-36-300x47.png 300w, https:\/\/blog.univ-angers.fr\/polytech_2A\/files\/2021\/06\/unknown-36-500x79.png 500w\" sizes=\"auto, (max-width: 605px) 100vw, 605px\" \/><\/a><\/p>\n<p><em>1.3 Branchements<\/em><br \/>\n<a href=\"https:\/\/blog.univ-angers.fr\/istiaprojetsei2\/files\/2021\/06\/unknown-37.png\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/blog.univ-angers.fr\/istiaprojetsei2\/files\/2021\/06\/unknown-37.png\" alt=\"unknown (37)\" width=\"605\" height=\"243\" class=\"alignnone size-full wp-image-1886\" srcset=\"https:\/\/blog.univ-angers.fr\/polytech_2A\/files\/2021\/06\/unknown-37.png 605w, https:\/\/blog.univ-angers.fr\/polytech_2A\/files\/2021\/06\/unknown-37-300x120.png 300w, https:\/\/blog.univ-angers.fr\/polytech_2A\/files\/2021\/06\/unknown-37-500x200.png 500w\" sizes=\"auto, (max-width: 605px) 100vw, 605px\" \/><\/a><\/p>\n<p><em>1.4 Programmes n\u00e9cessaires<\/em><\/p>\n<p>Vous pourrez trouver <a href=\"https:\/\/uabox.univ-angers.fr\/index.php\/s\/2vTWBp1szTPK1zP\">ici<\/a> les deux fichiers \u00e0 t\u00e9l\u00e9charger. Le lien est valable jusqu\u2019au 31 Aout 2021. Pass\u00e9 cette date et si n\u00e9cessaire, vous pouvez envoyer un courriel \u00e0 zfourrier@etud.univ-angers.fr afin que je vous fournisse un nouveau lien.<br \/>\nL\u2019application sert en tant qu\u2019administrateur, \u00e0 changer le texte affich\u00e9 lorsqu\u2019un p\u00e9riph\u00e9rique se connecte en bluetooth. Attention : Elle ne marche que sur les appareils android.<br \/>\nL\u2019application demande un login (admin) + mot de passe (modpass). Ils ne sont pas modifiables car le seul moyen d\u2019obtenir cette application est par ce lien, ce qui repr\u00e9sente la majeure partie de la s\u00e9curit\u00e9. Il existe une deuxi\u00e8me couche de s\u00e9curit\u00e9 pour \u00e9viter la modification \u00e0 l\u2019aide d\u2019un terminal bluetooth par exemple. Le programme n\u2019acceptera de nouveaux indices que lorsqu\u2019il est en \u00e9tat \u00ab ouvert \u00bb. Pour le passer en mode \u00ab Ferm\u00e9 \u00bb, il faut envoyer \u00ab STOP \u00bb via l\u2019application, et pour l\u2019ouvrir \u00e0 nouveau, il faut envoyer ce mot de passe : \u00ab Jri4fg74 \u00bb. Cela permet \u00e0 l\u2019administrateur d\u2019\u00eatre le seul \u00e0 pouvoir changer le mot de passe affich\u00e9 pendant le fonctionnement normal.<br \/>\nLe programme arduino est simple et court, et largement comment\u00e9 pour le cas o\u00f9 un bug se produirait, je le pr\u00e9senterai plus en d\u00e9tail dans une partie suivante.<br \/>\nIl vous faut uploader le programme Bluetooth.ino sur l\u2019ESP32 via l\u2019IDE Arduino.<\/p>\n<p><strong>2\u00e8me \u00e9tape : Fonctionnement et Utilisation<\/strong><\/p>\n<p>La partie setup est tr\u00e8s simple, on commence par l\u2019initialisation de l\u2019ESP32 en bluetooth, on lui donne un nom et on affiche dans le moniteur s\u00e9rie que le p\u00e9riph\u00e9rique est pr\u00eat \u00e0 \u00eatre utilis\u00e9. La deuxi\u00e8me partie consiste \u00e0 initialiser l\u2019\u00e9cran LCD et d\u00e9sactiver le r\u00e9tro\u00e9clairage. L\u2019\u00e9cran n\u2019affiche rien pour le moment.<\/p>\n<p><code>void setup() {<br \/>\n    Serial.begin(115200);<br \/>\n    SerialBT.begin(\"Polytech treasure hunt\"); \/\/Bluetooth device name<br \/>\n    Serial.println(\"The device started, now you can pair it with bluetooth!\");<br \/>\n    lcd.init();<br \/>\n    lcd.noBacklight();<br \/>\n}<\/code><\/p>\n<p>Quand un p\u00e9riph\u00e9rique est connect\u00e9 en bluetooth (un smartphone dans la plupart des cas qui vont se pr\u00e9senter), voil\u00e0 ce qu\u2019il se passe :<\/p>\n<p><code>if(SerialBT.available()){<br \/>\n      lcd.backlight();<br \/>\n      LCDPrint(clue); \/\/ Lights up the screen and prints the current clue when a device is connected <\/code><\/p>\n<p>On allume le r\u00e9tro\u00e9clairage et on affiche le mot de passe actuel.<\/p>\n<p><code>}else{<br \/>\n      lcd.noBacklight;<br \/>\n      LCDPRINT(\"\");<br \/>\n    }<\/code><br \/>\nEnfin, quand plus aucun appareil n\u2019est connect\u00e9, l\u2019\u00e9cran s\u2019\u00e9teint et tout le texte est effac\u00e9&#8230;<\/p>\n<p>Nous avons couvert la totalit\u00e9 des interactions de l\u2019utilisateur, nous allons maintenant passer \u00e0 l\u2019interface administrateur.<br \/>\nPour commencer \u00e0 param\u00e9trer le mot de passe, vous devez vous munir d\u2019un t\u00e9l\u00e9phone avec l\u2019application Polytech Angers Treasure Hunt Admin (elle appara\u00eetra peut-\u00eatre de cette mani\u00e8re dans votre liste d\u2019applications :<br \/>\n <a href=\"https:\/\/blog.univ-angers.fr\/istiaprojetsei2\/files\/2021\/06\/unknown-38.png\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/blog.univ-angers.fr\/istiaprojetsei2\/files\/2021\/06\/unknown-38.png\" alt=\"\" width=\"42\" height=\"56\" class=\"alignnone size-full wp-image-1892\" \/><\/a><br \/>\nSur l\u2019\u00e9cran d\u2019accueil, vous pourrez entrer le login et le mot de passe fournis pr\u00e9c\u00e9demment dans ce document (paragraphe 1.4), puis vous aurez acc\u00e8s au panneau de configuration. Cette fois encore, vous pourrez tr\u00e8s simplement entrer l\u2019indice que vous d\u00e9sirez afficher sur l\u2019\u00e9cran, cliquer sur le bouton send et l\u2019\u00e9cran devrait se mettre \u00e0 jour. Par s\u00e9curit\u00e9, il est recommand\u00e9 d\u2019envoyer STOP juste apr\u00e8s, de mani\u00e8re \u00e0 emp\u00eacher un  utilisateur poss\u00e9dant un terminal bluetooth de modifier l\u2019indice pour poser probl\u00e8me aux autres utilisateurs.<br \/>\nSi l\u2019appareil est verrouill\u00e9 (n\u2019accepte pas de nouveaux indices) et que quelqu\u2019un essaie de changer l\u2019indice, un message demandant le mot de passe s\u2019affichera pendant 5 secondes sur l\u2019\u00e9cran LCD. La proc\u00e9dure pour le d\u00e9verrouiller est d\u00e9crite au paragraphe 1.4. Il est \u00e0 noter qu\u2019apr\u00e8s un red\u00e9marrage, l\u2019indice affich\u00e9 sera celui par d\u00e9faut et l\u2019appareil sera en mode ouvert (accepte un nouvel indice). Vous pouvez trouver et modifier l\u2019indice par d\u00e9faut ici :<br \/>\n<code> String clue = \"fvopdjsbodfps\"; \/\/ default clue<br \/>\n<\/code><br \/>\nDe la m\u00eame mani\u00e8re, si vous pr\u00e9f\u00e9rez que l\u2019appareil d\u00e9marre en mode ferm\u00e9, il suffit de changer la ligne suivante<br \/>\n<code> int receivingNewCodes = 0 ; <\/code><br \/>\nEn<br \/>\n<code> int receivingNewCodes = 1 ; <\/code><\/p>\n<p><strong><font color=\"red\">Projet n\u00b05 :  Code secret sous forme d\u2019un code PIN &#8211; R\u00e9alis\u00e9 par Th\u00e9o ROY<\/strong><\/font><\/p>\n<p>Le but de mon projet est de r\u00e9aliser un clavier tactile \u00e0 code PIN.<br \/>\nJe vais donc vous montrer comment le coder.<\/p>\n<p>Mot cl\u00e9 : 2.4 \u2018\u2019 TFT LCD SHIELD, Arduino, clavier tactile, code PIN <\/p>\n<p><strong>1\u00e8re \u00e9tape : Pr\u00e9paration<\/strong><\/p>\n<p><em>Mat\u00e9riel :<\/em><br \/>\n&#8211;\tCarte Arduino Uno<br \/>\n&#8211;\tEcran 2.4 \u2018\u2019 TFT LCD SHIELD<\/p>\n<p><em>Branchement :<\/em><br \/>\nLe branchement est simple, l\u2019\u00e9cran s\u2019emboite sans probl\u00e8me avec l\u2019arduino uno<\/p>\n<p><em>Librairie :<\/em><br \/>\nSPFD5408 (<a href=\"https:\/\/cutt.ly\/MnGW3RL\">https:\/\/cutt.ly\/MnGW3RL<\/a>)<br \/>\nCette librairie contient toutes les librairies n\u00e9cessaires <\/p>\n<p><strong>2\u00e8me \u00e9tape : Pr\u00e9paration du code<\/strong><br \/>\n<em><br \/>\nD\u00e9finitions des PINs :<\/em><br \/>\n<code>#define YP A1<br \/>\n#define XM A2<br \/>\n#define YM 7<br \/>\n#define XP 6<br \/>\n#define LCD_CS A3<br \/>\n#define LCD_CD A2<br \/>\n#define LCD_WR A1<br \/>\n#define LCD_RD A0<br \/>\n#define LCD_RESET A4<\/code><\/p>\n<p><em>Calibrage de l\u2019\u00e9cran:<\/em><br \/>\n<code>#define TS_MINX 125<br \/>\n#define TS_MINY 85<br \/>\n#define TS_MAXX 965<br \/>\n#define TS_MAXY 905<\/code><br \/>\n<em><br \/>\nD\u00e9finition des couleurs et de la pression :<\/em><br \/>\n<code>#define WHITE   0x0000<br \/>\n#define YELLOW    0x001F<br \/>\n#define CYAN     0xF800<br \/>\n#define PINK   0x07E0<br \/>\n#define RED    0x07FF<br \/>\n#define GREEN 0xF81F<br \/>\n#define BLUE  0xFFE0<br \/>\n#define BLACK   0xFFFF<br \/>\n#define MINPRESSURE 10<br \/>\n#define MAXPRESSURE 1000<\/code><\/p>\n<p>De la m\u00eame mani\u00e8re que le projet n\u00b01, il faut trouver le code hexad\u00e9cimal du driver et l\u2019\u00e9crire dans le void setup().<\/p>\n<p><em>Configuration de l\u2019\u00e9cran (300 est la sensibilit\u00e9) : <\/em><br \/>\n<code>TouchScreen ts = TouchScreen(XP, YP, XM, YM, 300); <\/code><\/p>\n<p><em>Communication avec le LCD :<\/em><br \/>\n<code>Adafruit_TFTLCD tft(LCD_CS, LCD_CD, LCD_WR, LCD_RD, LCD_RESET);<\/code> <\/p>\n<p><strong>3\u00e8me \u00e9tape : Affichage du clavier \u00e0 code.<\/strong><br \/>\n<a href=\"https:\/\/blog.univ-angers.fr\/istiaprojetsei2\/files\/2021\/06\/unknown-39.png\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/blog.univ-angers.fr\/istiaprojetsei2\/files\/2021\/06\/unknown-39.png\" alt=\"\" width=\"218\" height=\"286\" class=\"alignnone size-full wp-image-1936\" \/><\/a><br \/>\nPour l\u2019affichage du clavier j\u2019ai cr\u00e9\u00e9 une fonction draw_Buttons() que j\u2019utilise dans le void setup(), comme cela elle va apparaitre au d\u00e9marrage du programme.<br \/>\n<em><br \/>\nAffichage des colonnes :<\/em><br \/>\nJ\u2019utilise la fonction tft.fillRect qui se construit de la fa\u00e7on suivante :<br \/>\n<code>tft.fillRect( pos.x, pos.y, longueur, hauteur, couleur) ; <\/code><br \/>\nCela va cr\u00e9er un rectangle rempli de la couleur choisi. <\/p>\n<p><em>Affichage des lignes verticales et horizontales :<\/em><br \/>\nJ\u2019utilise la fonction tft.drawFastHLine qui se construit de la fa\u00e7on suivante :<br \/>\n<code>tft.drawFastHLine( pos.x, pos.y, longueur, couleur) ; <\/code><br \/>\nCela va cr\u00e9er une ligne horizontale. De la m\u00eame mani\u00e8re pour la ligne verticale avec tft.drawFastVLine.<br \/>\n<em><br \/>\nAffichage de la zone de texte :<\/em><br \/>\nDe la m\u00eame fa\u00e7on que les colonnes avec la fonction tft.fillRect.<br \/>\n<em><br \/>\nAffichage des caract\u00e8res du clavier :<\/em><br \/>\nPour \u00e9crire du texte nous allons avoir besoin de 4 fonctions.<br \/>\n La premi\u00e8re est tft.setCursor qui sert \u00e0 placer le point de d\u00e9part du texte :<br \/>\n<code>tft.setCursor( pos.x, pos.y) ; <\/code><br \/>\nEnsuite il y a tft.TextColor qui va changer la couleur du texte :<br \/>\n<code>tft.setTextColor(couleur);<\/code><br \/>\nPuis, pour g\u00e9rer la taille du texte il y a la fonction tft.setTextSize :<br \/>\n<code>tft.setTextSize(n); <\/code><br \/>\nEnfin pour \u00e9crire du texte, tft.println  , qui \u00e9crit tous les caract\u00e8res non sp\u00e9ciaux :<br \/>\n<code>tft.println(\u201c \u201d);<\/code><\/p>\n<p>Pour afficher les caract\u00e8res, j\u2019ai mis ces fonctions dans une boucle associ\u00e9e \u00e0 un matrice :<br \/>\n<code>String symbol[4][4] = {<br \/>\n  { \"7\", \"8\", \"9\", \"\" },<br \/>\n  { \"4\", \"5\", \"6\", \"\" },<br \/>\n  { \"1\", \"2\", \"3\", \"\" },<br \/>\n  { \"X\", \"0\", \"V\", \"?\" }<br \/>\n};<br \/>\n <\/code><\/p>\n<p><strong>4\u00e8me \u00e9tape : Programmer les boutons <\/strong><\/p>\n<p><em>Bouton chiffre :<\/em><br \/>\nChaque bouton correspondant \u00e0 un chiffre est configur\u00e9 de cette mani\u00e8re :<br \/>\n<code>if (X50)<br \/>\nif (Y&gt;85 &amp;&amp; Y&lt;140) \/\/Bouton 3<br \/>\n    \t\t{Serial.println (&quot;Bouton 3&quot;);<br \/>\n    \t\t result = true;<br \/>\n    \t\t Number = (Number*10) + 3;<br \/>\n    \t\t } <\/code><br \/>\n&#8211;\t<code>if<\/code> (\u2026) : Correspond \u00e0 la position de la touche<br \/>\n&#8211;\t<code>result = true<\/code> : Permet la saisie du texte<br \/>\n&#8211;\t<code>Number<\/code> : Correspond au code<\/p>\n<p><em>Bouton valider :<\/em><br \/>\n<code>if (Y&gt;85 &amp;&amp; Y&lt;140) \/\/Valider<br \/>\n    {Serial.println (&quot;Valider&quot;);<br \/>\n     result = false;<br \/>\n     tft.fillRect(0, 0, 240, 80, CYAN);<br \/>\n     tft.setCursor(10, 20);<br \/>\n     tft.setTextSize(2);<br \/>\n     if (Number == Code) {<br \/>\n      tft.println(&quot;Bon Code&quot;);<br \/>\n      delay(1000);<br \/>\n     }else{<br \/>\n      tft.println(&quot;Mauvais Code&quot;);<br \/>\n     }<\/code><br \/>\n&#8211;\t<code>result = false <\/code>: Arr\u00eat de la saisie<br \/>\n&#8211;\t<code>tft.fillRect() <\/code>: Permet d\u2019effacer en recr\u00e9ant le rectangle<br \/>\n&#8211;\tEnsuite, tout d\u00e9pend si le code est le bon.<\/p>\n<p><em>Bouton Effacer :<\/em><br \/>\n<code>if (Y&gt;192 &amp;&amp; Y&lt;245) \/\/Effacer<br \/>\n    {Serial.println (&quot;Bouton Effacer&quot;);<br \/>\n    Number=0;<br \/>\n    result = false;<br \/>\n    tft.fillRect(0, 0, 240, 80, CYAN);<br \/>\n    }<\/code><br \/>\n&#8211;\t<code>Number = 0<\/code> : R\u00e9initialiser le code<br \/>\n&#8211;\t<code>tft.fillRect()<\/code> : Permet d\u2019effacer en recr\u00e9ant le rectangle<br \/>\n&#8211;\t<code>result = false<\/code> : Arr\u00eat de la saisie<\/p>\n<p><em>Bouton Aide :<\/em><br \/>\n<code>if (Y&gt;0 &amp;&amp; Y&lt;85) \/\/Aide<br \/>\n    {Serial.println (&quot;Aide&quot;);<br \/>\n     result = false;<br \/>\n     tft.fillRect(0, 0, 240, 80, CYAN);<br \/>\n     tft.setCursor(10, 20);<br \/>\n     tft.setTextSize(2);<br \/>\n     tft.println(&quot;Code \u00e0 4 chiffres&quot;);<br \/>\n     }<\/code><br \/>\n&#8211;\t<code>tft.fillRect()<\/code> : Permet d\u2019effacer en recr\u00e9ant le rectangle<br \/>\n&#8211;\t<code>tft.println()<\/code> : Permet d\u2019afficher un texte<\/p>\n<p>Et voici une petite vid\u00e9o qui montre comment ce projet fonctionne :<br \/>\n<a href=\"https:\/\/www.youtube.com\/watch?v=AxCin9HA1Iw\">https:\/\/www.youtube.com\/watch?v=AxCin9HA1Iw<\/a><br \/>\n<div style=\"width: 360px;\" class=\"wp-video\"><video class=\"wp-video-shortcode\" id=\"video-1478-1\" width=\"360\" height=\"640\" preload=\"metadata\" controls=\"controls\"><source type=\"video\/mp4\" src=\"https:\/\/blog.univ-angers.fr\/istiaprojetsei2\/files\/2021\/06\/Demo.mp4?_=1\" \/><a href=\"https:\/\/blog.univ-angers.fr\/istiaprojetsei2\/files\/2021\/06\/Demo.mp4\">https:\/\/blog.univ-angers.fr\/istiaprojetsei2\/files\/2021\/06\/Demo.mp4<\/a><\/video><\/div><\/p>\n<p>Code complet : <a href=\"https:\/\/cutt.ly\/DnHyFnG\">https:\/\/cutt.ly\/DnHyFnG<\/a><\/p>\n<p><strong>Conclusion <\/strong><\/p>\n<p>Nous avons tous r\u00e9ussi \u00e0 mener a bien nos projets et \u00e0 les finaliser. M\u00eame s&#8217;il y a sans doute des choses \u00e0 am\u00e9liorer, tous les projets fonctionnent.<br \/>\nCe n&#8217;\u00e9tait pas vraiment un projet d&#8217;\u00e9quipe, car nous avions chacun notre projet, mais il a \u00e9t\u00e9 tr\u00e8s enrichissant pour chacun.<br \/>\nCet article touche \u00e0 sa fin. Nous esp\u00e9rons que ces projets vous ont aid\u00e9 \u00e0 r\u00e9aliser les v\u00f4tres.<br \/>\nMerci de votre lecture. <\/p>\n","protected":false},"excerpt":{"rendered":"<p>Bonjour \u00e0 tous, Nous sommes 4 \u00e9tudiants de PeiP 2, Th\u00e9o ROY, Zacharie FOURRIER, Alexandre PRAT et Eli DESTOMBES. Dans le cadre de notre projet de conception nous avons travaill\u00e9 sur une display-box. L&#8217;objectif de notre projet est de r\u00e9aliser &hellip; <a href=\"https:\/\/blog.univ-angers.fr\/polytech_2A\/2021\/06\/04\/display-box\/\">Continuer la lecture <span class=\"meta-nav\">&rarr;<\/span><\/a><\/p>\n","protected":false},"author":74172,"featured_media":0,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[344],"tags":[43,252,437,442,436,243],"class_list":["post-1478","post","type-post","status-publish","format-standard","hentry","category-344","tag-arduino","tag-bluetooth","tag-ecran-lcd","tag-ecran-oled","tag-ecran-tactile","tag-polytech-angers"],"_links":{"self":[{"href":"https:\/\/blog.univ-angers.fr\/polytech_2A\/wp-json\/wp\/v2\/posts\/1478","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/blog.univ-angers.fr\/polytech_2A\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/blog.univ-angers.fr\/polytech_2A\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/blog.univ-angers.fr\/polytech_2A\/wp-json\/wp\/v2\/users\/74172"}],"replies":[{"embeddable":true,"href":"https:\/\/blog.univ-angers.fr\/polytech_2A\/wp-json\/wp\/v2\/comments?post=1478"}],"version-history":[{"count":1,"href":"https:\/\/blog.univ-angers.fr\/polytech_2A\/wp-json\/wp\/v2\/posts\/1478\/revisions"}],"predecessor-version":[{"id":1820,"href":"https:\/\/blog.univ-angers.fr\/polytech_2A\/wp-json\/wp\/v2\/posts\/1478\/revisions\/1820"}],"wp:attachment":[{"href":"https:\/\/blog.univ-angers.fr\/polytech_2A\/wp-json\/wp\/v2\/media?parent=1478"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/blog.univ-angers.fr\/polytech_2A\/wp-json\/wp\/v2\/categories?post=1478"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/blog.univ-angers.fr\/polytech_2A\/wp-json\/wp\/v2\/tags?post=1478"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}