Joystick Status Display Using LCD

Joystick Status Display Using LCD

HARDWARE REQUIRED:

  • PICUNO Microcontroller board
  • 1 × 16x2 I2C LCD Display
  • 1 × HW-504 Joystick Module
  • Jumper wires
  • USB cable
  • 9V Battery with a snap connector (to power the board via the DC Jack)

DESCRIPTION:

This project creates a simple but powerful user interface by reading all the inputs from a Joystick XY module and displaying them in real-time. The program continuously reads the Analog values from the X and Y axes to get a 2D coordinate, as well as the digital state of the built-in push-button. This data is then formatted and sent to a 16x2 I2C LCD screen for immediate feedback. This project serves as a fundamental building block for any system that requires user control, such as games, navigation menus, or robot controllers.

CIRCUIT DIAGRAM:

Joystick Status Display Using LCD
  • Connect the LCD Module's GND pin to a GND pin on board.
  • Connect the LCD Module's VCC pin to the 5V pin on board.
  • Connect the LCD Module's SDA pin GPIO 4 (SDA Pin on PICUNO).
  • Connect the LCD Module's SCL pin GPIO 5 (SCL Pin on PICUNO).
  • JOYSTICK MODULE:
    • Connect the VCC pin to 5V pin on the board.
    • Connect the GND pin to GND pin on board.
    • Connect the VRx pin to Analog Pin A0 (GPIO 26).
    • Connect the VRy pin to Analog Pin A1 (GPIO 27).
    • Connect the SW (Switch) pin to GPIO 8.

SCHEMATIC:

LCD VCC → 5V

LCD GND → GND

LCD SDA → GPIO 4 (Board SDA Pin)

LCD SCL → GPIO 5 (Board SCL Pin)

Joystick Module:

VCC → 5V

GND → GND

VRx → A0

VRy → A1

SW → GPIO 8

CODE -- C:

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

// Pin Definitions
const int JOY_X_PIN = A0;
const int JOY_Y_PIN = A1;
const int JOY_SW_PIN = 8;

// LCD Setup
LiquidCrystal_I2C lcd(0x27, 16, 2);

void setup() {
  pinMode(JOY_SW_PIN, INPUT_PULLUP);
  
  lcd.init();
  lcd.backlight();
  lcd.print("Joystick Test");
  delay(1000);
}

void loop() {
  // Read the values from the joystick
  int xValue = analogRead(JOY_X_PIN);
  int yValue = analogRead(JOY_Y_PIN);
  int swValue = digitalRead(JOY_SW_PIN);

  // Clear the screen and display values
  lcd.clear();
  
  // Display X and Y values on the top line
  lcd.setCursor(0, 0);
  lcd.print("X:");
  lcd.print(xValue);
  
  lcd.setCursor(8, 0);
  lcd.print("Y:");
  lcd.print(yValue);

  // Display the button state on the bottom line
  lcd.setCursor(0, 1);
  lcd.print("Switch: ");
  if (swValue == LOW) { // LOW means pressed because of INPUT_PULLUP
    lcd.print("Pressed");
  } else {
    lcd.print("Off");
  }

  delay(200);
}
pinMode(JOY_SW_PIN, INPUT_PULLUP); - Configures the joystick's button pin as an input and enables an internal resistor to keep the signal stable.

analogRead(JOY_X_PIN) - Reads the joystick's position on one axis as a value from 0-1023.

digitalRead(JOY_SW_PIN) - Reads the state of the button. Because we are using INPUT_PULLUP, the value will be LOW when pressed.

lcd.setCursor(col, row) - This command is used to precisely position the text on the screen before printing.

CODE -- PYTHON:

from machine import Pin, ADC, I2C
from i2c_lcd import I2cLcd
from time import sleep

adc_x = ADC(Pin(26)) # A0
adc_y = ADC(Pin(27)) # A1

# Setup Digital pin for Joystick Switch
button = Pin(8, Pin.IN, Pin.PULL_UP)

i2c = I2C(0, scl=Pin(5), sda=Pin(4))
lcd = I2cLcd(i2c, 0x27, 2, 16)

lcd.putstr("Joystick Test")
sleep(1)
lcd.clear()

while True:
  # Read all the values
  x_val = adc_x.read_u16()
  y_val = adc_y.read_u16()
  sw_val = button.value()
  
  # Format the text for display
  x_text = f"X:{x_val:<5}" # Format X value
  y_text = f"Y:{y_val:<5}" # Format Y value
  sw_text = f"Switch: {'Pressed' if sw_val == 0 else 'Off'}"

  # Display on the LCD
  lcd.move_to(0, 0)
  lcd.putstr(f"{x_text} {y_text}")
  
  lcd.move_to(0, 1)
  lcd.putstr(f"{sw_text:<16}")
  
  sleep(0.2)
adc_x = ADC(Pin(26)) - Creates an Analog-to-Digital Converter object for the X-axis pin.

button = Pin(8, Pin.IN, Pin.PULL_UP) - Configures the button pin as an input with an internal pull-up resistor.

x_val = adc_x.read_u16() - Reads the joystick's X-axis position as a 16-bit value (0-65535).

sw_text = f"Switch: {'Pressed' if sw_val == 0 else 'Off'}" - This is a conditional expression (ternary operator) inside an f-string. It neatly formats the button status into the correct string in one line.

lcd.putstr(...) - Prints the final formatted strings to the LCD screen.