Basic LCD I2C Programming Commands
From the C-tech curriculum
TL;DR
You'll use an I2C module to simplify controlling an LCD screen with fewer wires, sending data and commands over just two lines. This involves initialising the LCD, setting the cursor position, and then printing text.
1. The Mental Model
Think of I2C as a dedicated postal service for your microcontroller and LCD. Instead of sending individual letters for every single character or command, you package everything up, address it to the I2C module, and it handles the delivery, telling the LCD what to do.
2. The Core Material
Controlling an LCD via I2C involves sending specific commands to its I2C adapter. This adapter then translates those commands into the parallel signals the LCD understands. This dramatically reduces the number of pins you need on your microcontroller, typically down to two (SDA and SCL) plus power and ground.
Here's how the basic communication flow works:
graph TD
A["Microcontroller"] --> B["I2C Module (on LCD)"];
B --> C{"LCD Display"};
C -- "Receives & Displays" --> D["User Sees Output"];
subgraph Microcontroller Actions
M1["Initialize I2C Library"] --> M2["Set LCD Address"];
M2 --> M3["Send Command (e.g., clear, cursor)"];
M3 --> M4["Send Data (characters)"];
end
M1 --> B;
M4 --> B;
Most Arduino libraries (like LiquidCrystal_I2C) abstract away the low-level I2C communication. You'll primarily interact with functions that map directly to common LCD actions.
Initialising the LCD

Photo by Francesco Paggiaro on Pexels
Before you can do anything, you need to tell your microcontroller how to talk to the I2C module. This involves specifying the I2C address of the LCD and its dimensions (columns and rows).
#include <Wire.h> // Required for I2C communication
#include <LiquidCrystal_I2C.h> // Library for I2C LCD
// Set the LCD's I2C address (common ones are 0x27 or 0x3F)
// Check your I2C module for the correct address or run an I2C scanner sketch
const int LCD_ADDR = 0x27;
// Define the number of columns and rows for your LCD
const int LCD_COLS = 16;
const int LCD_ROWS = 2;
// Create an LCD object
LiquidCrystal_I2C lcd(LCD_ADDR, LCD_COLS, LCD_ROWS);
void setup() {
// Initialize the LCD
lcd.init();
// Turn on the backlight
lcd.backlight();
// Print a message to the LCD.
// This is often used to confirm initialization.
lcd.print("Hello, C-tech!");
}
void loop() {
// Your main code goes here
}
Setting the Cursor Position

Photo by Pixabay on Pexels
To display text exactly where you want it, you need to move the cursor. LCDs are addressed by column and row, starting from (0,0) for the top-left character.
// Move cursor to column 0, row 0 (top-left)
lcd.setCursor(0, 0);
lcd.print("Line 1");
// Move cursor to column 5, row 1 (sixth character, second line)
lcd.setCursor(5, 1);
lcd.print("Line 2 here");
Clearing the Display

Photo by Joseph Russo on Pexels
Sometimes you want to erase everything on the screen and start fresh.
lcd.clear(); // Clears the entire display and sets cursor to (0,0)
Printing Text

Photo by Markus Winkler on Pexels
Once the cursor is set, you use print() to display characters. This works just like Serial.print().
// After setting cursor, print text
lcd.print("My Text");
// You can print variables too
int value = 123;
lcd.print("Value: ");
lcd.print(value); // Will display "Value: 123"
Turning Backlight On/Off
You can control the backlight if your I2C module supports it.
lcd.backlight(); // Turns backlight ON
lcd.noBacklight(); // Turns backlight OFF
3. Worked Example
Let's make your LCD display a simple count-up timer that updates every second on the first line, and a static message on the second line.
#include <Wire.h>
#include <LiquidCrystal_I2C.h>
const int LCD_ADDR = 0x27; // Confirm this address for your module
const int LCD_COLS = 16;
const int LCD_ROWS = 2;
LiquidCrystal_I2C lcd(LCD_ADDR, LCD_COLS, LCD_ROWS);
unsigned long previousMillis = 0;
const long interval = 1000; // Update every 1 second
int counter = 0;
void setup() {
lcd.init();
lcd.backlight();
lcd.clear(); // Clear any previous garbage
// Print the static message on the second line once
lcd.setCursor(0, 1);
lcd.print("Timer: ");
}
void loop() {
unsigned long currentMillis = millis();
if (currentMillis - previousMillis >= interval) {
previousMillis = currentMillis; // Save the last time you updated
// Update the counter
counter++;
// Clear the first line before printing new counter value
// This prevents "ghosting" if the new number is shorter than the old one
lcd.setCursor(0, 0);
lcd.print(" "); // Print spaces to clear the line
// Set cursor to the start of the first line and print the counter
lcd.setCursor(0, 0);
lcd.print("Count: ");
lcd.print(counter);
}
}
4. Key Takeaways
- The I2C module greatly reduces wiring complexity, needing only two data lines (SDA, SCL).
- You must include
Wire.hand a specific I2C LCD library (e.g.,LiquidCrystal_I2C.h). - Always check the correct I2C address (
0x27or0x3Fare common) for your module. lcd.init()andlcd.backlight()are crucial setup calls.lcd.setCursor(col, row)places the cursor for printing, with(0,0)being the top-left.lcd.clear()erases the display and resets the cursor to(0,0).
Common mistakes to avoid:
- Using the wrong I2C address, which will result in a blank or unresponsive display.
- Forgetting lcd.init() or lcd.backlight() in setup().
- Not clearing previous text when updating, leading to overlapping characters.
- Forgetting to include Wire.h, which handles the low-level I2C communication.
5. Now Try It
Modify the worked example. Instead of a simple counter, make the LCD display "Temperature: XX.X C" on the first line and "Humidity: YY.Y %" on the second line. Use placeholder values for temperature and humidity (e.g., float temp = 25.5; float hum = 60.2;) and update them every 2 seconds. Success means the LCD clearly shows both values on separate lines, updating smoothly without text overlap.
Frequently asked about Basic LCD I2C Programming Commands
Study this next
Get the full C-tech curriculum
Clone the complete plan to your dashboard for unlimited AI-generated notes, practice quizzes, and a personalised revision schedule.
Save this course free