theme | paginate | footer | header | auto-scaling | size | color | backgroundColor | tags | date created | date modified | |||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
default |
true |
© Copyright 2024, Adrian Gould & NM TAFE |
 |
true |
4k |
#ccc |
#060606 |
|
03 July 2024 |
10 July 2024 |
Qty | Item | Notes |
---|---|---|
1 | Breadboard | |
1 | GPIO Expansion | |
1 | ESP32 | |
1 | LCD 16x2 module | |
4 | Jumper | Male-Female |
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
Important:
On this circuit the VCC connection goes to the 5V line.
A breadboard equivalent is shown below:
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;
}