Accéder au contenu principal

Ecran ITEAD 1602 LCD pour le FEZ Panda II ou le Fez Cerbuino Bee

L'écran FEZ Touch fait plus que largement l'affaire pour la plupart des usages (écran couleur 320x240, tactile, affichage rapide, bitmaps, etc). Pour des usages simples ou sur le FEZ Cerbuino Bee, il peut cependant être utile d'avoir un écran LCD simple. J'ai craqué pour l'ITEAD 1602 LCD Shield d'ITEAD Studio (http://imall.iteadstudio.com/development-platform/arduino/shields/im120417018.html) en promotion pour 5 USD.
L'écran LCD est un écran de 2 lignes rétro-éclairé en bleu. Il dispose de 4 écrans de direction (haut, bas, gauche, droite), d'un bouton Reset (à droite) et d'un bouton Select (à gauche). Il reprend également les 5 ports analogiques au pas 2,54 cm, par contre, il n'y a pas de reprise de port digitaux. Il est cependant possible de l'empiler sur une carte Grove de manière à utiliser les quelques ports digitaux encore utilisables.
Le driver de GHI Electronics Black Shield convient largement. Je l'ai légèrement adapté avec du code Netduino pour pouvoir faire des défilements et des caractères graphiques. Voici le driver correspondant.

 //BLACK SHIELD DRIVER  
 /*  
 Copyright 2010 GHI Electronics LLC  
 Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at  
 http://www.apache.org/licenses/LICENSE-2.0  
 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.   
 */  
 using System;  
 using System.Threading;  
 using Microsoft.SPOT;  
 using Microsoft.SPOT.Hardware;  
 using GHIElectronics.NETMF.Hardware;  
 using GHIElectronics.NETMF.FEZ;  
 namespace ITEADStudio  
 {  
     static public class LCDKeypad  
     {  
       public enum Keys  
       {  
         Up,  
         Down,  
         Right,  
         Left,  
         Select,  
         None,  
       }  
       static OutputPort LCD_RS;  
       static OutputPort LCD_E;  
       static OutputPort LCD_D4;  
       static OutputPort LCD_D5;  
       static OutputPort LCD_D6;  
       static OutputPort LCD_D7;  
       static AnalogIn AnKey;  
       static OutputPort BackLight;  
       const byte DISP_ON = 0xC;  //Turn visible LCD on  
       const byte CLR_DISP = 1;   //Clear display  
       const byte CUR_HOME = 2;   //Move cursor home and clear screen memory  
       const byte SET_CURSOR = 0x80;  //SET_CURSOR + X : Sets cursor position to X  
       const byte SCROLL_LEFT = 0x18;   // scroll all rows 1 char left  
       const byte SCROLL_RIGHT = 0x1e;   // scroll all rows 1 char right  
       const byte CGRAM = 64; // writing memory location  
       const byte DDRAM = 128; // reading memory location  
       const byte DISPLAY_BLANK = 0x08;  // Blank display without clearing it  
       const byte DISPLAY_RESTORE = 0x0c; // restore display, cursor hidden  
       const byte EM_DECREMENT_OFF = 0x04; // fixed first char, scroll cursor left when printing  
       const byte EM_DECREMENT_ON = 0x05; // fixed last char, scroll all right when printing  
       const byte EM_INCREMENT_ON = 0x06; // fixed first char, move cursor right when printing  
       const byte EM_INCREMENT_OFF = 0x07; // fixed last char, scroll all left when printing  
       const byte CUR_INVISIBLE = 0x0c;  // set cursor to be invisible  
       const byte CUR_SET_POSITION = 0x80; //SET_CURSOR + X : Sets cursor position to X      
       const byte CUR_VISIBLE_BLINK_BOX = 0x0f;  
       const byte CUR_VISIBLE_UNDERLINE = 0x0e;  
       public static void Initialize(bool analogic)  
       {  
         LCD_RS = new OutputPort((Cpu.Pin)FEZ_Pin.Digital.Di8, false);  
         LCD_E = new OutputPort((Cpu.Pin)FEZ_Pin.Digital.Di9, false);  
         LCD_D4 = new OutputPort((Cpu.Pin)FEZ_Pin.Digital.Di4, false);  
         LCD_D5 = new OutputPort((Cpu.Pin)FEZ_Pin.Digital.Di5, false);  
         LCD_D6 = new OutputPort((Cpu.Pin)FEZ_Pin.Digital.Di6, false);  
         LCD_D7 = new OutputPort((Cpu.Pin)FEZ_Pin.Digital.Di7, false);  
         if (analogic)  
           AnKey = new AnalogIn((AnalogIn.Pin)FEZ_Pin.AnalogIn.An0);  
         BackLight = new OutputPort((Cpu.Pin)FEZ_Pin.Digital.Di10, true);  
         LCD_RS.Write(false);  
         // 4 bit data communication  
         Thread.Sleep(50);  
         LCD_D7.Write(false);  
         LCD_D6.Write(false);  
         LCD_D5.Write(true);  
         LCD_D4.Write(true);  
         LCD_E.Write(true);  
         LCD_E.Write(false);  
         Thread.Sleep(50);  
         LCD_D7.Write(false);  
         LCD_D6.Write(false);  
         LCD_D5.Write(true);  
         LCD_D4.Write(true);  
         LCD_E.Write(true);  
         LCD_E.Write(false);  
         Thread.Sleep(50);  
         LCD_D7.Write(false);  
         LCD_D6.Write(false);  
         LCD_D5.Write(true);  
         LCD_D4.Write(true);  
         LCD_E.Write(true);  
         LCD_E.Write(false);  
         Thread.Sleep(50);  
         LCD_D7.Write(false);  
         LCD_D6.Write(false);  
         LCD_D5.Write(true);  
         LCD_D4.Write(false);  
         LCD_E.Write(true);  
         LCD_E.Write(false);  
         SendCmd(DISP_ON);  
         SendCmd(CLR_DISP);  
       }  
       //Sends an ASCII character to the LCD  
       static void Putc(byte c)  
       {  
         LCD_D7.Write((c & 0x80) != 0);  
         LCD_D6.Write((c & 0x40) != 0);  
         LCD_D5.Write((c & 0x20) != 0);  
         LCD_D4.Write((c & 0x10) != 0);  
         LCD_E.Write(true); LCD_E.Write(false); //Toggle the Enable Pin  
         LCD_D7.Write((c & 0x08) != 0);  
         LCD_D6.Write((c & 0x04) != 0);  
         LCD_D5.Write((c & 0x02) != 0);  
         LCD_D4.Write((c & 0x01) != 0);  
         LCD_E.Write(true); LCD_E.Write(false); //Toggle the Enable Pin  
         //Thread.Sleep(1);  
       }  
       //Sends an LCD command  
       static void SendCmd(byte c)  
       {  
         LCD_RS.Write(false); //set LCD to data mode  
         LCD_D7.Write((c & 0x80) != 0);  
         LCD_D6.Write((c & 0x40) != 0);  
         LCD_D5.Write((c & 0x20) != 0);  
         LCD_D4.Write((c & 0x10) != 0);  
         LCD_E.Write(true); LCD_E.Write(false); //Toggle the Enable Pin  
         LCD_D7.Write((c & 0x08) != 0);  
         LCD_D6.Write((c & 0x04) != 0);  
         LCD_D5.Write((c & 0x02) != 0);  
         LCD_D4.Write((c & 0x01) != 0);  
         LCD_E.Write(true); LCD_E.Write(false); //Toggle the Enable Pin  
         Thread.Sleep(1);  
         LCD_RS.Write(true); //set LCD to data mode  
       }  
       /// <summary>  
       /// Print a string   
       /// </summary>  
       /// <param name="str"></param>  
       /// <param name="sleep"></param>  
       static void iPrint(string str, int sleep = 0)  
       {  
         for (int i = 0; i < str.Length; i++)  
         {  
           Putc((byte)str[i]);  
           Thread.Sleep(sleep);  
         }  
       }  
       public static void Clear()  
       {  
         SendCmd(CLR_DISP);  
       }  
       public static void CursorHome()  
       {  
         SendCmd(CUR_HOME);  
       }  
       public static void SetCursor(byte row, byte col)  
       {  
         SendCmd((byte)(SET_CURSOR | row << 6 | col));  
       }  
       public static Keys GetKey()  
       {  
         int i = AnKey.Read();  
         //if (i != 1023)  
         //  Debug.Print(i.ToString());  
         // use this to read values to calibrate  
         /*while (true)  
         {  
           i = AnKey.Read();  
           Debug.Print(i.ToString());  
           Thread.Sleep(300);  
         }*/  
         const int ERROR = 50;  
         if (i > 1024 - ERROR)  
           return Keys.None;  
         if (i < 0 + ERROR)  
           return Keys.Right;  
         if (i < 200 + ERROR && i > 200 - ERROR)  
           return Keys.Up;  
         if (i < 450 + ERROR && i > 450 - ERROR)  
           return Keys.Down;  
         if (i < 700 + ERROR && i > 700 - ERROR)  
           return Keys.Left;  
         if (i < 780 + ERROR && i > 780 - ERROR)  
           return Keys.Select;  
         return Keys.None;  
       }  
       public static void TurnBacklightOn()  
       {  
         BackLight.Write(true);  
       }  
       public static void ShutBacklightOff()  
       {  
         BackLight.Write(false);  
       }  
       /// <summary>  
       /// Scroll the display a number of places Left   
       /// The operation ay be paused a number of milliseconds between each movement to  
       /// provide annimation.  
       /// </summary>  
       /// <param name="counter"></param>  
       /// <param name="sleep"></param>  
       public static void DisplayScrollLeft(int counter = 1, int sleep = 0)  
       { while (counter-- > 1) { SendCmd(SCROLL_LEFT); ; Thread.Sleep(sleep); } }  
       /// <summary>  
       /// Scroll the display a number of places Right  
       /// The operation ay be paused a number of milliseconds between each movement to  
       /// provide annimation.  
       /// </summary>  
       /// <param name="counter"></param>  
       /// <param name="sleep"></param>  
       public static void DisplayScrollRight(int counter = 1, int sleep = 0)  
       {   
         while (counter-- > 1) {  
           SendCmd(SCROLL_RIGHT);  
           Thread.Sleep(sleep);   
         }  
       }  
       /// <summary>  
       /// Used to user define the first eight characters  
       /// Use (char)8 to print the first character instead of (char)0  
       /// If using a string of only custom characters terminate with + ""  
       /// </summary>  
       /// <param name="asciiCharPos"></param>  
       /// <param name="customChars"></param>  
       public static void SetCustomChars(byte asciiCharPos, byte[] customChars)  
       {  
         //if (customChars.Length > 8) throw new Exception("A byte array length greater than 8 will overwrite the following character");  
         // write a   
         SendCmd((byte)(CGRAM + (8 * asciiCharPos)));  
         for (byte i = 0; i < customChars.Length; i++)  
         {  
           Putc(customChars[i]);  
           Thread.Sleep(1);  
         }  
         SendCmd(DDRAM);  
       }  
       /// <summary>  
       /// Blank the display without clearing it  
       /// </summary>  
       public static void DisplayHide()  
       {  
         SendCmd(DISPLAY_BLANK);  
       }  
       /// <summary>  
       /// Restore display, cursor hidden  
       /// </summary>  
       public static void DisplayRestore()  
       {  
         SendCmd(DISPLAY_RESTORE);  
       }  
       /// <summary>  
       /// Fixed first char, move cursor right when printing  
       /// </summary>  
       public static void ModeForwardStatic()  
       {  
         SendCmd(EM_INCREMENT_ON);  
       }  
       /// <summary>  
       /// Fixed last char, scroll all left when printing  
       /// </summary>  
       public static void ModeForwardRunLeft()  
       {  
         SendCmd(EM_INCREMENT_OFF);  
       }  
       /// <summary>  
       /// Fixed last char, scroll all right when printing  
       /// </summary>  
       public static void ModeReversedStatic()  
       {  
         SendCmd(EM_DECREMENT_ON);  
       }  
       /// <summary>  
       /// ixed first char, scroll cursor left when printing  
       /// </summary>  
       public static void ModeReversedRunRight()  
       {  
         SendCmd(EM_DECREMENT_OFF);  
       }  
       public static void BacklightOn()  
       {  
         BackLight.Write(true);  
       }  
       public static void BacklightOff()  
       {  
         BackLight.Write(false);  
       }  
       public static void CursorInvisible()  
       {  
         SendCmd(CUR_INVISIBLE);  
       }  
       public static void CursorBlinkBox()  
       {  
         SendCmd(CUR_VISIBLE_BLINK_BOX);  
       }  
       public static void CursorUnderline()  
       {  
         SendCmd(CUR_VISIBLE_UNDERLINE);  
       }  
       /// <summary>  
       /// Places the cursor at a given row and column  
       /// Top left is 0 , 0  
       /// </summary>  
       /// <param name="row"></param>  
       /// <param name="col"></param>  
       public static void CursorSet(byte row, byte col)  
       {  
         SendCmd((byte)(CUR_SET_POSITION | row << 6 | col));  
       }  
       /// <summary>  
       /// Remove all data from all lines of the display  
       /// </summary>  
       public static void Clear(int delayBefore = 0)  
       {  
         Thread.Sleep(delayBefore);  
         SendCmd(CLR_DISP);  
       }  
       /// <summary>  
       /// Print a string with a pause ( milliseconds) between characters  
       /// </summary>  
       /// <param name="str"></param>  
       /// <param name="sleep"></param>  
       public static void Print(string str, int sleep)  
       {  
         iPrint(str, sleep);  
       }  
       /// <summary>  
       /// Print a string at a the current cursor location   
       /// </summary>  
       /// <param name="str"></param>  
       public static void Print(string str)  
       {  
         iPrint(str);  
       }  
       /// <summary>  
       /// Print a string at a location   
       /// </summary>  
       /// <param name="row"></param>  
       /// <param name="col"></param>  
       /// <param name="str"></param>  
       public static void Print(byte row, byte col, string str)  
       {  
         CursorSet(row, col);  
         iPrint(str);  
       }  
       /// <summary>  
       /// Print a string at a location with a pause ( milliseconds) between characters  
       /// </summary>  
       /// <param name="row"></param>  
       /// <param name="col"></param>  
       /// <param name="str"></param>  
       /// <param name="sleep"></param>  
       public static void Print(byte row, byte col, string str, int sleep)  
       {  
         CursorSet(row, col);  
         iPrint(str, sleep);  
       }  
     }  
 }  

Voici un exemple simple d'utilisation qui affiche des caractères et récupère la valeur des touches appuyées. Attention !!!. A cause d'un problème de voltage de la carte, la touche Select ne peut pas être détectée. Toutes les touches utilisent le même Pin analogique et des résistances sont associées à chaque touches. La résistance associée à la touche Select a une valeur de 0, ce qui ne permet pas de la distinguer du fait qu'aucune touche n'est enfoncée. Vu le prix de la carte, ce léger bug reste mineur. Il est toujours possible de connecter un bouton sur l'un des connecteurs libres.
     LCDKeypad.Initialize();  
     LCDKeypad.TurnBacklightOn();  
     int i = 0;  
     while (true)  
     {  
       LCDKeypad.CursorHome();  
       LCDKeypad.Print("Count " + i++);  
       LCDKeypad.SetCursor(1, 2);  
       switch (LCDKeypad.GetKey())  
       {  
         case LCDKeypad.Keys.Up:  
           LCDKeypad.Print("Up  ");  
           break;  
         case LCDKeypad.Keys.Down:  
           LCDKeypad.Print("Down ");  
           break;  
         case LCDKeypad.Keys.Left:  
           LCDKeypad.Print("Left ");  
           break;  
         case LCDKeypad.Keys.Right:  
           LCDKeypad.Print("Right ");  
           LCDKeypad.ShutBacklightOff();  
           break;  
         case LCDKeypad.Keys.Select:  
           LCDKeypad.Print("Select");  
           break;  
         case LCDKeypad.Keys.None:  
           LCDKeypad.Print("");  
           break;  
         }  
       Thread.Sleep(100);  
       }  

Il est possible d'utiliser cette carte pour des exemples plus complexes, comme un réveil, un instrument de mesure (température, hygrométrie, etc).

Commentaires

Posts les plus consultés de ce blog

Supprimer les partitions Raspberry sur une carte SD sous Windows 7 avec Diskpart

Si vous souhaitez récupérer une ancienne carte SD utilisée pour démarrer un Raspberry pour un autre usage (appareil photo, etc), il vous faudra supprimer les deux partitions créées au moment de l'écriture de l'image sur la carte SD. Vous pouvez voir les partition en sélectionnant Menu Windows/Ordinateur/bouton droit "Gérer". Voici un exemple du résultat final. Vous pouvez supprimer la partition Unix de 7 Gb (ou 4Gb en fonction de la taille de votre carte) en sélectionnant la partition puis en faisant "bouton droit Supprimer". Laissez juste une partition pour pouvoir faire les autres manipulations avec DISKPART. Démarrez l'outil DISKPART en ligne de commande. Une nouvelle fenêtre s'ouvrira. Microsoft DiskPart version 6.1.7601 Copyright (C) 1999-2008 Microsoft Corporation. Sur l'ordinateur : FRVILN0H305806 DISKPART> list disk   N° disque  Statut         Taille   Libre    Dyn  GPT   ---------  -------------  -------  -------  ---  ---   D

Comment lire son écran de téléphone Android sur PC (2)

Voici une nouvelle manière d'accéder à votre téléphone depuis votre PC. Cette méthode utilise le câble USB et Google Chrome. Elle fonctionne donc sur Windows, Mac et Linux. Les pré-requis sont les mêmes que ceux du billet précédent : Téléphone configuré en mode Développement Drivers USB installés sur le PC Google Chrome installé L'application Vysor s'installe comme une extension de Google Chrome. Cherchez dans le Webstore et lancez l'installation. Une fois installée, l'application apparaît dans les extensions. Vous pouvez la lancer de différentes manières. La manière la plus simple est d'ouvrir la fenêtre des applications : chrome://apps/ Une autre manière est de créer un raccourci en cliquant sur « Détails ». Ensuite créez un raccourci sur le bureau, le menu démarrer et/ou la barre de tâche. Vous pouvez également cliquer sur afficher dans la boutique et lancer l'application depuis la boutique. Une fois

Serveur d'impression CUPS sur Raspberry Pi

Je possède une très vieille imprimante laser HP Laserjet 6L noir et blanc de 12 ans d'age qui a survécu à plusieurs imprimantes jet d'encre couleurs tombées en désuétude pour obsolescence programmée. J'envisage tout de même sérieusement de les démanteler pour les recycler en CNC, graveur ou autre.   Je continue donc a utiliser cette bonne petite imprimante parallèle qui me rend bien des services (en 12 ans, j'ai changé le toner 3 fois pour un coût de 20 € la cartouche). J'ai donc dû m'équiper d'une adaptateur USB/Parallèle pour pouvoir la connecter sur un PC récent. Le problème principal est que le driver de cette imprimate n'est reconnu que par un seul de mes PC sous Windows 7. Les autres PC sous Windows 8 ou Windows 10 reconnaissent bien l'imprimante, mais sortent des feuilles avec le code Postscript. L'impression depuis une tablette ou un téléphone Androïd est également tout simplement impossible. Pour remédier à ce problème, j'ai don