Ad Code

Responsive Advertisement

Arduino Fundamentals with Mini Projects(Part-3)

Arduino Project-Based Learning Series

PART 3: Display & User Interface Projects

Introduction

In PART 1, we learned Arduino fundamentals using basic input and output projects.
In PART 2, we worked with sensors to make Arduino react to real-world conditions.

In PART 3, we focus on display and user interface (UI) projects.
Displays and input devices allow users to see data, change settings, and interact with Arduino systems.

This part introduces LCDs, keypads, and practical display-based projects used in real electronics and IoT systems.

What You Will Learn in PART 3

  • LCD interfacing with Arduino
  • I2C communication basics
  • Displaying sensor and voltage data
  • Keypad interfacing
  • Creating simple menu systems

Required Components

  • Arduino UNO / Nano
  • 16×2 LCD (parallel or I2C)
  • I2C LCD module
  • 4×4 keypad
  • Potentiometer (10kΩ)
  • Resistors & jumper wires
  • Breadboard

Project 9A: Digital Voltmeter Using Arduino

Project Objective

To measure and display DC voltage using Arduino.

Circuit Description

  • Voltage divider → A0
  • LCD → Arduino (I2C or parallel)
  • Ensure max input ≤ 10V
Digital Voltmeter Using Arduino
LCD Parallel Communication

Click here for a schematic diagram of it.

Arduino Code (Parallel Communication)



#include <LiquidCrystal.h>

LiquidCrystal lcd(2, 3, 4, 5, 6, 7);
int voltPin = A0;

void setup() 
{
  lcd.begin(16, 2);
  lcd.print("Digital Voltmeter");
}

void loop() 
{
  int value = analogRead(voltPin);
  float voltage = value * (10 / 1023.0);
  lcd.setCursor(0, 1);
  lcd.print("Volt: ");
  lcd.print(voltage);
  lcd.print(" V");
  delay(500);
}

Digital Voltmeter Using Arduino
LCD I2C Communication

Click here for a schematic diagram of it.

Arduino Code (I2C Communication)


#include <LiquidCrystal_I2C.h>
#include <Wire.h> 
// Initialize the LCD with the I2C address 0x27 and a 16x2 display
LiquidCrystal_I2C lcd(0x27, 16, 2);
int voltPin = A0;

void setup() 
{
  lcd.init();
  lcd.backlight();
  // set cursor at (0,0) position 
  lcd.setCursor(0, 0); 
  // Print a message to the LCD
  lcd.print("Hello, world!");    
  delay(5000);
  lcd.clear();
  lcd.setCursor(0, 0); 
  // Print a message to the LCD
  lcd.print("Digital Voltmeter"); 
   lcd.setCursor(0, 1);  
}

void loop() 
{
  int value = analogRead(voltPin);
  float voltage = value * (10 / 1023.0);
  lcd.setCursor(0, 1);
  lcd.print("Volt: ");
  lcd.print(voltage);
  lcd.print(" V");
  delay(500);
}

Applications

  • Power supply testing
  • Battery monitoring
  • Lab instruments

Project 10: Temperature Display on 16×2 LCD (I2C)

Project Objective

To display temperature data on an LCD using I2C communication.

Circuit Description

  • TMP36 → A0
  • LCD I2C → SDA, SCL
Temperature Display on 16×2 LCD (I2C) by Arduino

Arduino Code


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

LiquidCrystal_I2C lcd(0x27, 16, 2);
int tempPin = A0;

void setup() {
  lcd.init();
  lcd.backlight();
}

void loop() {
  int value = analogRead(tempPin);
  float temp = ((value * (5.0 / 1023.0))-0.5) * 100;

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

  delay(1000);
}

Working Principle

  • I2C uses only two wires (SDA & SCL)
  • Reduces pin usage
  • Ideal for complex projects

Project 11: 4×4 Keypad Interfacing with Arduino

Project Objective

To read user input from a keypad.

Circuit Description

  • Rows & columns connected to digital pins
  • Uses keypad scanning technique
4×4 Keypad Interfacing with Arduino

Arduino Code


#include <Keypad.h>

const byte rows = 4;
const byte cols = 4;

char keys[rows][cols] = {
  	{'1','2','3','A'},
  	{'4','5','6','B'},
	{'7','8','9','C'},
	{'*','0','#','D'}
	};

byte rowPins[rows] = {9,8,7,6};
byte colPins[cols] = {5,4,3,2};

Keypad keypad = Keypad(makeKeymap(keys), rowPins, colPins, rows, cols);

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

void loop() {
  char key = keypad.getKey();

  if (key) {
    Serial.print("Key Pressed: ");
    Serial.println(key);
  }
}

Applications

  • Password systems
  • Menu navigation
  • Access control

Project 12: Menu-Based System Using Keypad + LCD

Project Objective

To create a simple user-friendly menu system.

Circuit Description

We can change the temperature setting point on the keypad for high and low settings. Based on the temperature input, an alarm message will be displayed on the LCD. There are three LEDs for showing the current status. These indicators provide visual feedback to the user, allowing for quick assessment of the system's performance. Additionally, users can customize the alarm thresholds to suit their specific needs, enhancing overall functionality and user experience.

Click here for schematic diagram

Working Principle

  • Keypad changes menu options
  • LCD displays selected option
  • Logic based on if or switch cases

Sample Code:


#include <Keypad.h>
#include <Wire.h>
#include <LiquidCrystal_I2C.h> // Use LiquidCrystal_I2C.h for I2C version

// Define Keypad Layout
const byte ROWS = 4; // four rows
const byte COLS = 4; // four columns
char keys[ROWS][COLS] = {
  {'1','2','3','A'},
  {'4','5','6','B'},
  {'7','8','9','C'},
  {'*','0','#','D'}
};
byte rowPins[ROWS] = {9, 8, 7, 6}; // connect to the row pinouts of the keypad
byte colPins[COLS] = {5, 4, 3, 1}; // connect to the column pinouts of the keypad

Keypad customKeypad = Keypad(makeKeymap(keys), rowPins, colPins, ROWS, COLS);

// Initialize the LiquidCrystal library (adjust pins if not using standard setup)
LiquidCrystal_I2C lcd(0x27, 16, 2); 
const int tempSensorPin = A0;
const int interruptPin  = 2;
const int lowOutPin   = 11;
const int highOutPin  = 12;
const int normalOutPin = 13;
char customKey ;
// Menu state variable
int menuState = 0; // 0: Main Menu, 1: Sub Menu 1, 2: Sub Menu 2, etc.
int low = 30;
int high = 80;
int lastTemp = 1;
bool menuMode = false;
volatile bool menuRequested = false;
volatile unsigned long pressStart = 0;
String inputBuffer = "";
//..................................//
void keyHoldISR() {
  if (digitalRead(interruptPin) == LOW) {
    pressStart = millis();
  } else {
    if (millis() - pressStart >= 2000) {
      menuRequested = true;
    }
  }
}
//................................//

void setup() {
  pinMode(interruptPin, INPUT_PULLUP); 
  attachInterrupt(digitalPinToInterrupt(interruptPin), keyHoldISR, CHANGE);
  lcd.init();
  lcd.backlight();
  lcd.print("Welcome...");
  lcd.setCursor(0,1);
  lcd.print("electrical-info");
  delay(2000);
  lcd.clear();
  //displayMainMenu();
  
  pinMode(lowOutPin, OUTPUT);
  pinMode(highOutPin, OUTPUT);
  pinMode(normalOutPin, OUTPUT);
}

void loop()
{
  
  if (menuRequested) {
    menuMode = true;
    menuRequested = false;
    lcd.clear();
    lcd.print("Menu Loading...");
    delay(1000);
    lcd.clear();
    displayMainMenu();
  }

  if (menuMode) //keyPAd
  {
   char customKey = customKeypad.getKey();

  if (customKey) 
  {
    if (menuState == 0) 
    	{
      // Main menu options
      switch (customKey)
      		{
        	case '1':
          menuState = 1;
          displaySubMenu1();
          break;
        	case '2':
          menuState = 2;
          displaySubMenu2();
          break;
        	case '#': // Exit button
          //menuState =3;
        	menuMode = false;
        	lastTemp = 1;
        	lcd.clear();
          break;
     		 }
    	} 
  else if (menuState == 1) //view setting
  		{
      	// Sub Menu 1 options
      	switch (customKey) 
        		{
        
        		case '#': // back button
          		menuState = 0;
          		displayMainMenu();
         		 break;
      			}
   		 }
    else if (menuState == 2) //velue setings
  		{
      	 // Sub Menu 2 options
      	switch (customKey) 
        		{
        		case '1': // High setting
          		menuState = 3;
          		displaySubMenu21();
         		 break;
          		case '2': // Low setting
          		menuState = 4;
          		displaySubMenu22();
         		 break;
        		case '#': // Exit/back button
          		menuState = 0;
          		displayMainMenu();
         		 break;
      			}
   		 }
    
    
    else if (menuState == 3) 
  		{
      	// Sub Menu 21(High set) options
      if(customKey >= '0' && customKey <= '9')
      		{
        	inputBuffer += customKey;
   		 	lcd.setCursor(13,0);
    		//lcd.print("Value: ");
    		lcd.print(inputBuffer);
    		//lcd.print("   ");
      		}
      	switch (customKey) 
        		{     
          
          		case '*': // set temp
          		saveSetpoint();
          		menuState = 2;
          		displaySubMenu2();
         		 break;
        		case '#': // Exit/back button
          		menuState = 2;
          		displaySubMenu2();
         		 break;
      			}
   		 }
    else if (menuState == 4) 
  		{
      	// Sub Menu 22(Low set) options
      		 if(customKey >= '0' && customKey <= '9')
      		{
        	inputBuffer += customKey;
   		 	lcd.setCursor(13,0);
    		//lcd.print("Value: ");
    		lcd.print(inputBuffer);
    		//lcd.print("   ");
      		}
      	switch (customKey) 
        		{
        		case '*': // set temp
          		saveSetpoint();
          		menuState = 2;
          		displaySubMenu2();
         		 break;
        		case '#': // Exit/back button
          		menuState = 2;
          		displaySubMenu2();
         		 break;
      			}
   		 }
  }  
    
  }
  else 
  {
    handleTemperature();
  }
  
}

void displayMainMenu() {
  //lcd.clear();
  lcd.setCursor(0, 0);
  lcd.print("Main Menu:");
  lcd.print("1.View");
  lcd.setCursor(0, 1);
  lcd.print("2.Setting #.Quit");
}

void displaySubMenu1() { //View set points
  lcd.clear();
  lcd.setCursor(0, 0);
  lcd.print("SubMenu1:");
  lcd.print("#.back");
  lcd.setCursor(0, 1);
  lcd.print("low:");
  lcd.print(low);
  lcd.print(" High:");
  lcd.print(high);
}

void displaySubMenu2() {
  lcd.clear();
  lcd.setCursor(0, 0);
  lcd.print("SubMenu2: ");
  lcd.print("1.High");
  lcd.setCursor(0, 1);
  lcd.print("  2.Low #.back");
}
void displaySubMenu21() {
  lcd.clear();
  lcd.setCursor(0, 0);
  lcd.print("Set Hi Temp: ");
  lcd.setCursor(0, 1);
  lcd.print("*.Set  #.back");
  inputBuffer = "";
}
void displaySubMenu22() {
  lcd.clear();
  lcd.setCursor(0, 0);
  lcd.print("Set Low Temp: ");
  lcd.setCursor(0, 1);
  lcd.print("*.Set #.back");
  inputBuffer = "";
}

void saveSetpoint() {
  if (inputBuffer.length() == 0) return;

  float value = inputBuffer.toFloat();
 if(value<=150)
 		{if (menuState == 3)
        	{
          	high = value;
          	lcd.clear();
    		lcd.setCursor(0, 0);
    		lcd.print("High value saved");
          	delay(2000);
        	}
          
       	 else if (menuState == 4 )
         {
          low = value;
           lcd.clear();
    		lcd.setCursor(0, 0);
    		lcd.print("Low value saved");
           delay(2000);
         }
        }
  else
  {
   lcd.clear();
    lcd.setCursor(0, 0);
    lcd.print("Out of range");
    lcd.setCursor(0, 1);
    lcd.print("Put it again....");
    delay(2000);
  }
  
  inputBuffer = "";
}


void handleTemperature() 
{  int raw = analogRead(tempSensorPin);
  float voltage = (raw * (5.0 / 1023.0))-0.5;
  float temperature = voltage * 100.0;
  
 
 if(abs(temperature - lastTemp)>=1)
 {
   String state;
		digitalWrite(lowOutPin, LOW);
   		digitalWrite(highOutPin, LOW);
   		digitalWrite(normalOutPin, LOW);
   if (temperature < low) {
    				digitalWrite(lowOutPin, HIGH);
    				state = "Low";
         				  }
  else if (temperature > high) {
    				digitalWrite(highOutPin, HIGH);
    				state = "High";
 							   }
  else {
    	digitalWrite(normalOutPin, HIGH);
    	state = "Normal";
  		}

    lcd.setCursor(0,0);
    lcd.print("Temp:");
    lcd.print(temperature,1); // One digit aftr deciml
    lcd.print((char)176); // degree symbol
    lcd.print("C   ");
	lcd.setCursor(7,1);
    lcd.print("       ");
    lcd.setCursor(0,1);
    lcd.print("State:");
    lcd.print(state);
    lastTemp = temperature;
   }
  
    delay(10);
}

Applications

  • Industrial controllers
  • Smart appliances
  • Configuration panels

Common Errors & Troubleshooting

  • Wrong I2C address
  • LCD shows nothing (contrast issue)
  • Keypad pins mismatch
  • Missing libraries

Frequently Asked Questions (FAQ)

Q1: How to find I2C address of LCD?
👉 Use I2C scanner sketch.

Q2: Can I use Arduino Nano instead of UNO?
👉 Yes, fully compatible.

Q3: Which display is best for beginners?
👉 16×2 I2C LCD is the easiest.

Conclusion

In PART 3, you learned how to:

  • Display data on LCD
  • Build interactive systems
  • Design user interfaces for Arduino projects

These skills are crucial for professional embedded systems and IoT dashboards.

Next Part

PART 4: Communication & Data Logging Projects
(Serial communication, SD card, RTC)

Post a Comment

0 Comments

Ad Code

Responsive Advertisement