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

Utilisez votre tablette Android comme second écran pour Linux (Raspberry Pi, MK908II)

Les tablettes Android atteignent désormais des prix qui défient toute concurrence. On trouve désormais des modèles à 39 € TTC en super marché, soit à peine plus cher que le Raspberry PI, mais avec un écran. Ces modèles souvent mono-core 1Ghz ou 1,4 Ghz avec 512 ou 1Go de mémoire ne sont très probablement pas utilisables pour une utilisation régulière sur Internet et ne sont en aucun point comparables à leur équivalent de marque (Samsung, Sony, LG, HTC, Lenovo, etc). Plusieurs tutoriels indiquent comment connecter utiliser une tablette Android comme second écran ( http://www.linux-magazine.com/Online/Blogs/Productivity-Sauce/Use-an-Android-Device-as-Screen-and-Input-for-Raspberry-Pi ). Ces méthodes utilisent généralement l'USB Tethering qui n'est malheureusement disponible que sur les téléphones ou tablettes avec un accès mobile (3G ou 4G) inclus. Dans ce billet, je vais vous montrer comment se connecter à une tablette en utilisant le mode Debug adb (Android Debug Bridge

Supprimer les partitions Raspberry sur une carte SD sous Windows 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. DISKPART> list disk   N° disque  Statut         Taille   Libre    Dyn  GPT   ---------  -------------  -------  -------  ---  ---   Disque 0    En ligne        238 G octe

Emulateur Raspberry Pi sous Windows

Si vous souhaitez développer ou tester des applications pour Raspberry Pi, vous pouvez, soit compiler directement l'application sur Raspberry, soit la développer sous Linux ou Windows et la compiler pour Raspberry. La seconde solution est souvent plus simple car elle permet de disposer d'un environnement de compilation complet tel qu'Eclipse pour le développement. Une fois l'application développée, il faut la tester sur Raspberry. Là, il faut copier l'application en utilisant un client FTP ou SCP, puis se connecter en SSH et lancer l'exécutable. Il existe un autre moyen de tester une application Raspberry sans avoir à l'allumer. Il suffit de passer par un émulateur tel que QEMU qui permet de lancer un OS pour processeur ARM sous Linux ou Windows. L'émulateur sous Windows 1. Récupérez l'émulateur à l'adresse suivante : http://sourceforge.net/projects/rpi-emulator-win32/ . 2. Dézippés le contenu de l'image Rpi-Occidentalis-v02-qemu.7z av