LCD1602 DFRobot Shield for Arduino HD44780 Display

Learn C/C++ and assembly language with Arduino LCD display shield. Links to college courses in embedded programming.

 

HARDWARE LIST
1 Arduino UNO
1 DFRobot 1602 Shield for Arduino

 

Story

I bought the Artou version of this shield. My first move was to use an ohmmeter to buzz out the connections between the display unit and the IO pins to the Arduino board. Frabjous day! It matched the pins used by the DFRobot shield.

 

 

DFRobot LCD Shield has a wiki page with sample programs and documents. The buttons connect to analog input A0. Many IO pins from the Uno board are available as through-hole or headers.

 

Connections

We find out that RS Register Select is connected to Arduino pin 8 and Enable is on pin 9. Display pins D4, D5, D6 and D7 are wired to matching board pins 4, 5, 6 and 7. RW Ready/Wait is not connected and not used in software.

 

 

LiquidCrystal Library

Arduino comes, by default, with the LiquidCrystal library to use this display. We have an ATmega8 project using the same display and the same library but this time we need to change the default connection leads.

 

 

The examples in the library will work but we have to modify what is called a constructor.

 

Modify Constructor

In OOP object oriented programming we are instantiating a data object of type LiquidCrystal named lcd. The return value of lcd(variables) depends upon the bits transmitted on the various wires. All examples in the LiquidCrystal library expect 4 data leads and two control leads.

 

 

 

 

 

Replace the two lines that tell software which leads to use with this updated line. The DFrobot Shield and copies are wired this way. Compile the sketch immediately to check. It is during these edits that mistakes are made.

 

LiquidCrystal lcd(8, 9, 4, 5, 6, 7);

 

By including the LiquidCrystal library we add defined functions to exchange data with the display module. Overloading is a C++ feature where defined functions are ready for 8bit or 4bit operation.

 

Open Example

Menu File->Examples->LiquidCrystal->CustomCharacter locate the constructor line and update to correct wiring details. #include <LiquidCrystal.h> is an important command, it adds a library of code to control the display.

 

 

Upload to our Uno board and we should see a little animation. This updated sketch is attached to this project.

 

 

The Buttons

Look at the schematic and you see the reset that restarts the board and you see a ladder of resistances connecting to Analog Input 0. The voltage going to A0 depends upon which buttons are pressed.

 

 

Compile and upload the pacMan.ino sketch attached to this project. Goal is for PacMan to eat all the energy pills before the monster eats him. Move PacMan with your buttons and restart game with reset.

 

 

Next Steps

Go through all the examples in the LiquidCrystal library and change the constructor. Upload to board and watch results. Use the examples from DFRobot. Do Embedded Engineering project to compare C/C++, Arduino IDE and assembly language programming of this same display device.

 

DFRobotCustomChar.ino

CODE
// include the library code:
#include <LiquidCrystal.h>

// constructor modified for leads in DFRobot 1602 LCD Shield

LiquidCrystal lcd(8, 9, 4, 5, 6, 7);

// make some custom characters:
byte heart[8] = {
  0b00000,
  0b01010,
  0b11111,
  0b11111,
  0b11111,
  0b01110,
  0b00100,
  0b00000
};

byte smiley[8] = {
  0b00000,
  0b00000,
  0b01010,
  0b00000,
  0b00000,
  0b10001,
  0b01110,
  0b00000
};

byte frownie[8] = {
  0b00000,
  0b00000,
  0b01010,
  0b00000,
  0b00000,
  0b00000,
  0b01110,
  0b10001
};

byte armsDown[8] = {
  0b00100,
  0b01010,
  0b00100,
  0b00100,
  0b01110,
  0b10101,
  0b00100,
  0b01010
};

byte armsUp[8] = {
  0b00100,
  0b01010,
  0b00100,
  0b10101,
  0b01110,
  0b00100,
  0b00100,
  0b01010
};

void setup() {
  // initialize LCD and set up the number of columns and rows:
  lcd.begin(16, 2);

  // create a new character
  lcd.createChar(0, heart);
  // create a new character
  lcd.createChar(1, smiley);
  // create a new character
  lcd.createChar(2, frownie);
  // create a new character
  lcd.createChar(3, armsDown);
  // create a new character
  lcd.createChar(4, armsUp);

  // set the cursor to the top left
  lcd.setCursor(0, 0);

  // Print a message to the lcd.
  lcd.print("I ");
  lcd.write(byte(0)); // when calling lcd.write() '0' must be cast as a byte
  lcd.print(" Arduino! ");
  lcd.write((byte)1);

}

void loop() {
  // read the potentiometer on A0:
  int sensorReading = analogRead(A0);
  // map the result to 200 - 1000:
  int delayTime = map(sensorReading, 0, 1023, 200, 1000);
  // set the cursor to the bottom row, 5th position:
  lcd.setCursor(4, 1);
  // draw the little man, arms down:
  lcd.write(3);
  delay(delayTime);
  lcd.setCursor(4, 1);
  // draw him arms up:
  lcd.write(4);
  delay(delayTime);
}

 

 

pacMan.ino

CODE
//Pacman
//Written By: Jean Malha
//http://forum.snootlab.com/viewtopic.php?f=34&t=207
// https://github.com/dadecoza/arduino-lcd-keypad-shield-games/blob/5f6cf624a5ca7a7b83d6dccb28bbe4f933850f50/sketches/Pacman/Pacman.ino

//#include "Wire.h" // insertion de la librairie I2C (obligatoire)
//#include <Deuligne.h> // insertion de la librairie Deuligne (obligatoire)
#include <LiquidCrystal.h>


#define VITESSE_PAC 150
#define VITESSE_FANT 2000
#define MAXX 15
#define MAXY 1

#define btnRight     0
#define btnUp        1
#define btnDown      2
#define btnLeft      3
#define btnSelect    4
#define btnNone      5

void(* resetFunc) (void) = 0;
LiquidCrystal lcd(8, 9, 4, 5, 6, 7); 


//Deuligne lcd; // Déclaration de l'objet lcd


// Charactère spécifique pacman
byte pacman[8] = {
  B00000,
  B00000,
  B01110,
  B11011,
  B11100,
  B01110,
  B00000,
  B00000
};

// Charactère spécifique fantome
byte fantome[8] = {
  B00000,
  B00000,
  B01110,
  B10101,
  B11111,
  B11111,
  B10101,
  B00000
};

byte point[8] = {
  B00000,
  B00000,
  B00000,
  B01110,
  B01110,
  B00000,
  B00000,
  B00000
};

// Tableau des points à manger
byte points[MAXX+1][MAXY+1];

int xpac=2; // Position de pacman en X (colone)
int ypac=1; //position de pacmanen y (ligne)
int xfant=15;// Position du fantome en X (colone)
int yfant=0;// Position du fantome en Y (ligne)
byte light=true; //Eclairage
long keystruck=0; //dernier appui sur un bouton
long poursuite=0; //dernier movement du fantome
byte partieEnCours=true; // pour eviter de boucler sur la fin
byte vide=false; // pour tester si tout est manger

byte level=0; // niveau
int score=0; // niveau

void bouge(int x,int y) // fonction pour bouger pacman
{
  int oldx=xpac;
  int oldy=ypac;
  if (((xpac+x)>=0)&((xpac+x)<=MAXX)) xpac=xpac+x; //Si pas sorti d'ecran, on change x
  if (((ypac+y)>=0)&((ypac+y)<=MAXY)) ypac=ypac+y;//Si pas sorti d'ecran, on change y
  lcd.setCursor(xpac,ypac); // On se place en nouvelle position
  lcd.write(byte(0)); // et on pose le caractere 0 (Pacman)
  lcd.setCursor(oldx,oldy); // On se place en ancienne position
  if ((xpac!=oldx)||(ypac!=oldy)) lcd.print(" "); // et on efface Pacman (s'il a bougé)
  if(points[xpac][ypac]){
    points[xpac][ypac]=false; // mange le truc
    score++;
  }
  vide=true;
  for (int i=0; i<=MAXX; i=i+1)
    for (int j=0; j<=MAXY; j=j+1)
      if (points[i][j])  vide=false;
  if ((vide)&&(partieEnCours)) gagne();
}

void perdu(){
  lcd.setCursor(0, 0); // on se place au point 0,0 (1ere ligne, 1er caractere)
  lcd.print("***Game Over****"); // on écrit le début du texte de début
  lcd.setCursor(0, 1); // on se place au point 0,1 (2eme ligne, 1er caractere)
  lcd.print("***");
  lcd.print(score);
  lcd.print("***"); 
  delay(2000);
  resetFunc();
}

void gagne()
{
  level++;
  lcd.setCursor(0, 0); // on se place au point 0,0 (1ere ligne, 1er caractere)
  lcd.print("*** Next level ***"); // on écrit le début du texte de début
  lcd.setCursor(0, 1); // on se place au point 0,0 (1ere ligne, 1er caractere)
  lcd.print("*** ");
  lcd.print(level,DEC);
  lcd.print(" ***"); // on écrit le début du texte de début
  delay(2000); // 2 secondes de pause
  initLevel(); //reinitialisation du tableau
}

void poursuis() // fonction pour bouger fantome
{
  int oldx=xfant;
  int oldy=yfant;
  if (yfant<ypac) yfant=yfant+1;
  else if (yfant>ypac) yfant=yfant-1;
  else if (xfant<xpac) xfant=xfant+1;
  else if (xfant>xpac) xfant=xfant-1;
  lcd.setCursor(xfant,yfant); // On se place en nouvelle position
  lcd.write(1); // et on pose le caractere 0 (Fantome)
  lcd.setCursor(oldx,oldy); // On se place en ancienne position
  if ((oldx!=xfant)||(oldy!=yfant)) // et on efface Fantome (s'il a bougé)
  {
    if (points[oldx][oldy]) lcd.write(2); // remplacé par un point si pas mangé
    else lcd.print(" "); // remplacé par un espace si déja magé
  }
}

//initialisation du tableau 
void initLevel(){
  for (int i=0; i<=MAXX; i=i+1)
    for (int j=0; j<=MAXY; j=j+1){
      points[i][j]=true; //initialisation du tableau des trucs à manger
      lcd.setCursor(i-1, j-1); // on se place au point j,i 
      lcd.write(2); // on écrit les points
    }
  lcd.setCursor(xpac,ypac); // On se place en position de départ de pacman
  lcd.write(byte(0)); // et on pose le caractere 0 (Pacman)
  lcd.setCursor(xfant,yfant); // On se place en position de départ du fantome
  lcd.write(1); // et on pose le caractere 1 (fantome)
  poursuite=millis(); // On initialise le timer de poursuite (pour eviter un mouvement immédiat)
  vide=false;
}

void setup() {
  Serial.begin(9600);
  //Wire.begin(); // initialisation I2C (obligatoire)
  //lcd.init(); // initialisation LCD (obligatoire)
  lcd.begin(16, 2);
  lcd.createChar(0, pacman); // creation du caractere pacman et affectation au numéro 0
  lcd.createChar(1, fantome); // creation du caractere de fantome et affectation au numéro 1
  lcd.createChar(2, point); // creation du caractere de point et affectation au numéro 2
  //lcd.backLight(true); // on allume le retro eclairage
  lcd.setCursor(0, 0); // on se place au point 0,0 (1ere ligne, 1er caractere)
  lcd.print("Pacman!"); // on écrit le début du texte de début
  delay (5000); // Splash screen
  initLevel(); // initialisation du tableau
}

void loop() {
  int thisChar = Serial.read();
  switch (thisChar)
  {
  case 'r':
    lcd.scrollDisplayRight();
    break;
  case 'l':
    lcd.scrollDisplayLeft();
    break;
  }
  if ((thisChar>'a')&(thisChar<'z'))
  {
    lcd.setCursor(1,1);
    lcd.write(thisChar);
  }
  if (millis()-keystruck>VITESSE_PAC) // Si plus de 200ms depuis le dernier mouvement de joystick
  {
    int joy=getKey();
    switch (joy)
    {
    case btnNone:
      break;
    case btnLeft:
      Serial.print("Pacman bouge à gauche.\n"); // envoi de controle sur liaison série
      Serial.print(keystruck);
      bouge(-1,0);// déplacement
      keystruck=millis(); // remise à zero du timer de mouvement
      break;
    case btnRight:
      Serial.print("Pacman bouge à droite\n");// envoi de controle sur liaison série
      bouge(1,0);// déplacement
      keystruck=millis(); // remise à zero du timer de mouvement
      break;
    case btnUp:
      Serial.print("Pacman bouge en haut\n");// envoi de controle sur liaison série
      bouge(0,-1);// déplacement
      keystruck=millis(); // remise à zero du timer de mouvement
      break;
    case btnDown:
      Serial.print("Pacman bouge en bas\n");
      bouge(0,1);// déplacement
      keystruck=millis(); // remise à zero du timer de mouvement
      break;
      /*case 4:
       Serial.print("centre\n");
       light=!light; //On inverse le statut d'allumage
       lcd.backLight(light); // on applique
       keystruck=millis(); // remise à zero du timer de mouvement
       break;*/
    default:
      Serial.print(joy); //au cas ou...
      keystruck=millis(); // remise à zero du timer de mouvement
    }; 
  };
  if (millis()-poursuite>VITESSE_FANT/(level+1)+10)
  {
    poursuis();
    poursuite=millis();
  }
  if ((xpac==xfant)&&(ypac==yfant)&&(partieEnCours)) 
  {
    perdu();
  }
}


int getKey() {
  int b = analogRead(A0);
  if (b > 1000) return btnNone;
  delay(8);
  if (b < 50) return btnRight;
  if (b < 180) return btnUp;
  if (b < 330) return btnDown;
  if (b < 520) return btnLeft;
  if (b < 700) return btnSelect;
}
License
All Rights
Reserved
licensBg
0