Raspberry Pi Pico + DS3231 RTC Digital Clock With 16x2 I2C LCD

by ElectroScope Archive in Circuits > Raspberry Pi

14 Views, 0 Favorites, 0 Comments

Raspberry Pi Pico + DS3231 RTC Digital Clock With 16x2 I2C LCD

RTC Module with Raspberry Pi Pico.jpg

In this build, I’m going to show you exactly how I made a simple but very accurate digital clock using a Raspberry Pi Pico, a DS3231 RTC module, and a 16x2 I2C LCD.

The cool part is that the RTC keeps time even when the Pico is powered off, thanks to its coin cell battery. The LCD cycles between time/date and temperature automatically, so we get more info without adding extra buttons.

This is a straightforward project. If you follow the wiring and upload the code properly, you’ll have it running in under an hour.

Supplies

DS3231-Pinout.jpg

Raspberry Pi Pico

DS3231 RTC module (with CR2032 battery installed)

16x2 LCD with I2C backpack

Breadboard

Jumper wires

USB cable for Pico

Install the Required Libraries

Open Arduino IDE.

Make sure you have support installed for Raspberry Pi Pico boards. If not, add the Pico board package first.

Now install these two libraries from Library Manager:

  1. RTClib (by Adafruit)
  2. LiquidCrystal_I2C (by johnrickman)

These handle communication with the DS3231 and the LCD.

That’s it. No extra stuff required.

Wiring Everything

RTC-With-Pico-Wiring-Diagram.jpg
RTC-With-Pico-Breadboard-Connection.jpg

This project uses I2C, which is nice because both the RTC and the LCD share the same two communication wires.

On the Raspberry Pi Pico:

  1. GP4 → SDA
  2. GP5 → SCL
  3. 3.3V → VCC
  4. GND → GND

Connect DS3231

  1. VCC → 3.3V
  2. GND → GND
  3. SDA → GP4
  4. SCL → GP5

Connect LCD (I2C backpack)

  1. VCC → 3.3V
  2. GND → GND
  3. SDA → GP4
  4. SCL → GP5

Both modules share SDA and SCL. That’s how I2C works. Each device has its own address.

The DS3231 default address is 0x68.

The LCD backpack is usually 0x27.

Double check:

  1. Battery is inserted into DS3231
  2. No loose wires
  3. SDA and SCL not swapped

If SDA/SCL are reversed, nothing works.

Upload Basic Test Code First

Before building the full clock, I always test the RTC alone.

Here’s a minimal test:


#include <Wire.h>
#include "RTClib.h"

RTC_DS3231 rtc;

void setup() {
Serial.begin(9600);
Wire.begin();

if (!rtc.begin()) {
Serial.println("RTC not found");
while (1);
}

if (rtc.lostPower()) {
rtc.adjust(DateTime(F(__DATE__), F(__TIME__)));
}
}

void loop() {
DateTime now = rtc.now();

Serial.print(now.hour());
Serial.print(":");
Serial.print(now.minute());
Serial.print(":");
Serial.println(now.second());

delay(1000);
}

Upload it. Open Serial Monitor.

If you see time counting properly, your RTC is working.

If it says "RTC not found", check wiring.

Important: Setting the Time Properly

The DS3231 only needs to be set once.

You have two options.

Option 1: Auto set from computer

This line sets the RTC using your computer’s compile time:


rtc.adjust(DateTime(F(__DATE__), F(__TIME__)));

Steps:

  1. Uncomment the line
  2. Upload immediately
  3. Then comment it again
  4. Upload again

If you don’t comment it out, the time resets every time the Pico restarts.

That’s a very common mistake.

Option 2: Set manually

If you want a specific date:


rtc.adjust(DateTime(2025, 11, 14, 15, 30, 0));

Format:

YEAR, MONTH, DAY, HOUR, MINUTE, SECOND

Again, upload once, then remove the line.

Add the LCD

Now let’s bring the LCD into the project.

Here’s the working clock code that:

  1. Displays date and time
  2. Switches to temperature
  3. Updates every second

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

RTC_DS3231 rtc;
LiquidCrystal_I2C lcd(0x27, 16, 2);

void setup() {
Wire.begin();
lcd.begin();
lcd.backlight();

if (!rtc.begin()) {
lcd.print("RTC NOT FOUND");
while (1);
}

if (rtc.lostPower()) {
rtc.adjust(DateTime(F(__DATE__), F(__TIME__)));
}
}

void loop() {
DateTime now = rtc.now();
float temp = rtc.getTemperature();

lcd.clear();
lcd.setCursor(0,0);
lcd.print("Time: ");
lcd.print(now.hour());
lcd.print(":");
lcd.print(now.minute());
lcd.print(":");
lcd.print(now.second());

lcd.setCursor(0,1);
lcd.print("Date: ");
lcd.print(now.day());
lcd.print("/");
lcd.print(now.month());
lcd.print("/");
lcd.print(now.year());

delay(3000);

lcd.clear();
lcd.setCursor(0,0);
lcd.print("Temperature:");
lcd.setCursor(0,1);
lcd.print(temp);
lcd.print(" C");

delay(3000);
}

That’s the whole thing.

How It Works

  1. Pico talks to RTC over I2C
  2. Pico talks to LCD over same I2C bus
  3. RTC provides time + temperature
  4. LCD prints formatted values
  5. Delays switch display modes

The DS3231 temperature sensor has 0.25°C resolution. It’s not lab grade, but it’s pretty decent.

Testing the Backup Battery

Unplug the USB.

Wait 30 seconds.

Plug it back in.

If the time continues correctly, your coin cell is working.

If time resets, check:

  1. Battery orientation
  2. Battery voltage
  3. Battery holder contacts

Common Problems and Fixes

LCD shows blank screen

  1. Check contrast screw on I2C backpack
  2. Confirm address is 0x27
  3. Try I2C scanner sketch if unsure

RTC not detected

  1. Check SDA and SCL wiring
  2. Make sure battery is inserted
  3. Try different jumper wires

Time resets every reboot

You forgot to comment out:


rtc.adjust(...)

Remove it and upload again.

Making It Cleaner

If you want it permanent:

  1. Use a small perf board
  2. Add header pins to Pico
  3. Use short wires
  4. Put it inside a small enclosure

You can power it from:

  1. USB
  2. 5V adapter
  3. Power bank

The RTC battery handles timekeeping when main power is gone.

That’s It

This is a solid little clock project. It’s simple, accurate, and easy to expand.

You could add:

  1. Alarm buzzer
  2. Buttons to set time
  3. 20x4 LCD
  4. OLED display
  5. Data logging

But as it stands, this is a clean, reliable DS3231 + Pico digital clock that just works.

If you wire it properly and set the time correctly once, you don’t need to touch it again.

This guide is completely based on: Raspberry Pi Pico RTC