Skip to content

Latest commit

 

History

History
221 lines (160 loc) · 5.17 KB

S06-LCD-16x2.md

File metadata and controls

221 lines (160 loc) · 5.17 KB
theme paginate footer header auto-scaling size color backgroundColor tags date created date modified
default
true
© Copyright 2024, Adrian Gould & NM TAFE
![NMTAFE](../images/Black-Red-Banner.svg)
true
4k
#ccc
#060606
Internet of Things
InterRIoT
IoT
Robotics
Python
Arduino
ESP-32
C
C++
03 July 2024
10 July 2024

Parts

Qty Item Notes
1 Breadboard
1 GPIO Expansion
1 ESP32
1 LCD 16x2 module
4 Jumper Male-Female

Arduino Project

Create a new Arduino project. Save it as ....

Add the following comment lines.

/**
 * LCD Display example
 *
 * Uses I2C to control the LCD.
 * Based on Freenove example.
 *
 * Arduino Filename: LCD-16x2-Example.ino
 *
 * Libraries: Arduino IDE shortcut - CTRL+SHIFT+I
 * - LiquidCrystal_I2C [Frank de Brabander]
 * - Wire
 *
 * Wiring:
 * - LCD PIN  JUMPER COLOUR   ESP PIN
 * - 1        Brown           GND
 * - 2        Red             5V
 * - 3        Orange          13
 * - 4        Yellow          14
 *
 */
 

Open the Libraries Tab in the Arduino IDE (CTRL+SHIFT+I) and add the following Libraries:

  • LiquidCrystal_I2C [Frank de Brabander]
  • Wire

Schematic for Circuit

Important:

On this circuit the VCC connection goes to the 5V line.

A breadboard equivalent is shown below:

Solution Code

Edit the Arduino project and add the code below:

Include the Liquid Crystal and Wire libraries:

#include <LiquidCrystal_I2C.h>
#include <Wire.h>

Define the pins the SDA and SCL lines are connected to (as per diagram and details above):

#define SDA 13  //Define SDA pins
#define SCL 14  //Define SCL pins

The LCD display uses an I2C driver chip, and as a result the address it is referenced at...

The kits we are using are based on the PCF8574AT and thus we use 0x27 as the address (Hex 27 = 71 Dec).

We also define the width and height of the LCD.

/*
 * I2C Chip: PCF8574T   0x27
 *           PCF8574AT  0x3F
 */
#define PCF8574T   0x27
#define PCF8574AT  0x3F 
#define LCD_I2C    0x27
#define LCD_WIDTH  16
#define LCD_HEIGHT 2

Define a constant for the period (in milliseconds) between updates to the display. In our case once every 1/10th of a second.

/* 1000ms = 1s */
#define UPDATE_PERIOD 100

Define the lcd object so that we can send data to it, defining the address, width and height.

LiquidCrystal_I2C lcd(LCD_I2C, LCD_WIDTH, LCD_HEIGHT);

Define our variables including a 'buffer' array that is used for each line of the LCD output.

unsigned long previousTime = 0;
unsigned long currentTime = 0;
int interval = UPDATE_PERIOD;
char buff[16];

Now we can set up the device.

Begin communication with the I2C device using the SDA and SCL lines.

  • SDA = Serial Data
  • SDC = Serial Clock

(More on this at https://learn.sparkfun.com/tutorials/i2c/all)

Next, test to see if the component (LCD) is connected to the I2C bus, checking PCF8574T address. If it is not on this address, we connect to the PCF8574AT address.

This is a user defined method that will be discussed later in these notes.

void setup() {
  Wire.begin(SDA, SCL);  // attach the I2C pin

  // Verify the component is connected
  if (!i2CAddrTest(PCF8574T)) {
    lcd = LiquidCrystal_I2C(PCF8574AT, LCD_WIDTH, LCD_HEIGHT);
  }

Now we may initialise the LCD, turn on the backlight and set the Cursor position to the 1st character on the 1st line...

Output some text to this line of the LCD.

  lcd.init();       // LCD driver initialization
  lcd.backlight();  // Turn On the backlight
  lcd.setCursor(0, 0);   // Move the cursor to row 1, column 1 (Top-Left)
  lcd.print("LCD I2C Demo");  // The print content is displayed on the LCD
}

The last part is to define a non blocking loop that updates the LCD every UPDATE_PERIOD milliseconds...

We have seen this non-blocking before, so we will not discuss here.

The only difference is how the text is added to the LCD.

We need to use the sprintf function (string print formatted), to create a string of text that includes the formatted output of the current time divided by 1000.

This string is placed into the text buffer array and then sent to the LCD.

void loop() {
  currentTime = millis();
  
  if ((currentTime - previousTime) >= UPDATE_PERIOD) {

	// Display output on line 2 of 
    // the LCD starting at column 1
    lcd.setCursor(0, 1);
    sprintf(buff, "Timer: %6.1f", ((float)currentTime) / 1000.0);
    lcd.print(buff);

    previousTime = currentTime;
  }
}

The last part of the code is a function to test the I2C Address to see if the component (our LCD) is connected or not.

To test we start transmitting on the I2Cbus to the address defined. If, on ending the transmission, we get a 0 result back then there is a device connected to the I2C bus at that address.

  
bool i2CAddrTest(uint8_t addr) {
  Wire.beginTransmission(addr);
  if (Wire.endTransmission() == 0) {
    return true;
  }
  return false;
}