Create an LCD (16x2) game with Raspberry Pi and Python

Create an LCD (16x2) game with Raspberry Pi and Python

Introduction

`Although it is an article on Mac environment, the procedure is the same for Windows environment. Please read and try the environment-dependent part. ``

Purpose

Create a math game using LCD1602A 16x2 I2C.

After reading this article to the end, you will be able to:

No. Overview keyword
1 Electronic circuit
2 LCD control SMBus
3 Button control gpiozero

specification

screen Button 1 Button 2
menu Selection of addition and subtraction Decision
addition Return to the menu by displaying the next question and displaying the 11th question Displaying the answer
subtraction Return to the menu by displaying the next question and displaying the 11th question Displaying the answer

Complete image

menu addition subtraction
IMG_4772.PNG IMG_4781.JPG IMG_4778.JPG
IMG_4782.PNG IMG_4774.JPG IMG_4776.JPG
IMG_4779.PNG IMG_4775.JPG IMG_4777.JPG

Execution environment

environment Ver.
macOS Catalina 10.15.6
Raspberry Pi 4 Model B 4GB RAM -
Raspberry Pi OS (Raspbian) 10
Python 3.7.3
gpiozero 1.5.1
RPi.GPIO 0.7.0
smbus2 0.3.0

Source code

I think that understanding will deepen if you read while actually following the implementation contents and source code. Please use it by all means.

GitHub

Related articles

-From Raspberry Pi setup to Python environment installation -Create a remote control car with Raspberry Pi and Python

Electronic circuit

LCD electronic circuit

lcd.png

Button electronic circuit

button.png

I2C settings

Launch Raspberry Pi Software Configuration Tool

command.sh


~$ sudo raspi-config

I2C enabled

  1. Select 5 Interfacing Options
  2. Select P5 I2C

Reboot

command.sh


~$ sudo reboot

I2C communication address confirmation

command.sh


~$ sudo i2cdetect -y 1
     0  1  2  3  4  5  6  7  8  9  a  b  c  d  e  f
00:          -- -- -- -- -- -- -- -- -- -- -- -- --
10: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
20: -- -- -- -- -- -- -- 27 -- -- -- -- -- -- -- --
30: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
40: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
50: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
60: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
70: -- -- -- -- -- -- -- --

The I2C communication address will be 0x27

Hands-on

command.sh


~$ git clone https://github.com/nsuhara/raspi-lcdgame.git -b master
~$ cd raspi-lcdgame

~$ python -m venv .venv
~$ source .venv/bin/activate
~$ pip install -r requirements.txt
~$ source config

~$ python app/main.py

~$ Control Key + C

App configuration

target.sh


/app
├─ addition.py
├─ i2clcd1602a
│      ├─ __init__.py
│      ├─ katakana.py
│      └─ pcf8574t.py
├─ main.py
├─ menu.py
├─ story_board.py
└─ subtraction.py

LCD

target.sh


/app
└─ i2clcd1602a
       ├─ __init__.py
       ├─ katakana.py
       └─ pcf8574t.py

LCD control

pcf8574t.py


"""i2clcd1602a/pcf8574t.py
"""
import time

from smbus2 import SMBus

from i2clcd1602a.katakana import convert


class LCD():
    """LCD
    """
    SMBUS_REV1 = 0
    SMBUS_REV2 = 1

    I2C_ADDR = 0x27

    ENABLE_BIT = 0b00000100

    LINE_1 = 0x80
    LINE_2 = 0xC0
    LINE_SIZE = 16

    MODE_COMMAND = 0
    MODE_CHAR = 1
    MODE_OPTION_BACKLIGHT = 0x08

    CMD_INITIALISE = 0x33
    CMD_SET_4_BIT_MODE = 0x32
    CMD_CURSOR_MOVE_DIRECTION = 0x06
    CMD_TURN_CURSOR_OFF = 0x0C
    CMD_2_LINE_DISPLAY = 0x28
    CMD_CLEAR_DISPLAY = 0x01
    CMD_WAIT = 0.0005

    def __init__(self):
        self.smbus = SMBus(self.SMBUS_REV2)

        self._send(mode=self.MODE_COMMAND, bits=self.CMD_INITIALISE)
        self._send(mode=self.MODE_COMMAND, bits=self.CMD_SET_4_BIT_MODE)
        self._send(mode=self.MODE_COMMAND, bits=self.CMD_CURSOR_MOVE_DIRECTION)
        self._send(mode=self.MODE_COMMAND, bits=self.CMD_TURN_CURSOR_OFF)
        self._send(mode=self.MODE_COMMAND, bits=self.CMD_2_LINE_DISPLAY)
        self._send(mode=self.MODE_COMMAND, bits=self.CMD_CLEAR_DISPLAY)

    def destroy(self):
        """destroy
        """
        self._send(mode=self.MODE_COMMAND, bits=self.CMD_CLEAR_DISPLAY)
        self.smbus.close()

    def message(self, message, line):
        """message
        """
        message = convert(message=message)
        message = message[0:self.LINE_SIZE]
        message = message.ljust(self.LINE_SIZE, ' ')

        self._send(mode=self.MODE_COMMAND | self.MODE_OPTION_BACKLIGHT,
                   bits=line)

        for char in message:
            self._send(mode=self.MODE_CHAR | self.MODE_OPTION_BACKLIGHT,
                       bits=ord(char))

    def clear(self):
        """close
        """
        self._send(mode=self.MODE_COMMAND | self.MODE_OPTION_BACKLIGHT,
                   bits=self.CMD_CLEAR_DISPLAY)

    def off(self):
        """off
        """
        self.destroy()

    def _send(self, mode, bits):
        """_send
        """
        higher_bits = mode | (bits & 0xF0)
        self._write(bits=higher_bits)

        lower_bit = mode | ((bits << 4) & 0xF0)
        self._write(bits=lower_bit)

    def _write(self, bits):
        """_write
        """
        self.smbus.write_byte(self.I2C_ADDR, bits)
        time.sleep(self.CMD_WAIT)

        self.smbus.write_byte(self.I2C_ADDR, (bits | self.ENABLE_BIT))
        time.sleep(self.CMD_WAIT)

        self.smbus.write_byte(self.I2C_ADDR, (bits & ~self.ENABLE_BIT))
        time.sleep(self.CMD_WAIT)

    def loop(self):
        """loop
        """
        while True:
            self.message(message='1234567890123456', line=self.LINE_1)
            self.message(message='abcdefghijklmnop', line=self.LINE_2)
            time.sleep(2)

            self.message(message='ABCDEFGHIJKLMNOP', line=self.LINE_1)
            self.message(message='Sashisuseso', line=self.LINE_2)
            time.sleep(2)


if __name__ == '__main__':
    lcd = LCD()
    try:
        print('start')
        lcd.loop()
    except KeyboardInterrupt:
        lcd.destroy()
        print('stop')

Katakana control

katakana.sh


"""i2clcd1602a/katakana.py
"""

SP_CODE = 0xfec0


def convert(message):
    """convert
    """
    converted = []
    for char in message:
        if ord(char) > SP_CODE:
            converted.append(chr(ord(char)-SP_CODE))
        else:
            converted.append(char)
    return ''.join(converted)

Main

target.sh


/app
└─ main.py

Main control

main.py


"""app/main.py
"""

from signal import pause
from time import sleep

from gpiozero import Button

from addition import Addition
from i2clcd1602a.pcf8574t import LCD
from menu import Menu
from subtraction import Subtraction


class Raspi():
    """Raspi
    """
    GPIO_BCM_BUTTON1 = 15
    GPIO_BCM_BUTTON2 = 25

    def __init__(self):
        self.lcd = LCD()

        self.button1 = Button(self.GPIO_BCM_BUTTON1)
        self.button1.when_pressed = self.button1_pressed
        self.button1.when_released = self.button1_released

        self.button2 = Button(self.GPIO_BCM_BUTTON2)
        self.button2.when_pressed = self.button2_pressed
        self.button2.when_released = self.button2_released

        self.status = 'menu'

        self.display = {
            'menu': Menu(self),
            'addition': Addition(self),
            'subtraction': Subtraction(self)
        }

        self.display.get(self.status).top()

    def destroy(self):
        """destroy
        """
        self.lcd.off()

    def button1_pressed(self):
        """button1_pressed
        """
        self.display.get(self.status).button1_pressed()

    def button1_released(self):
        """button1_released
        """
        self.display.get(self.status).button1_released()

    def button2_pressed(self):
        """button2_pressed
        """
        self.display.get(self.status).button2_pressed()

    def button2_released(self):
        """button2_released
        """
        self.display.get(self.status).button2_released()

    def pause(self):
        """pause
        """
        pause()


if __name__ == '__main__':
    app = Raspi()
    try:
        print('start')
        app.pause()
    except KeyboardInterrupt:
        app.lcd.clear()
        app.lcd.message(message='Good by...', line=app.lcd.LINE_1)
        sleep(1)
        app.destroy()
        print('stop')

Common

target.sh


/app
└─ story_board.py

Abstract class

story_board.py


"""app/story_board.py
"""

import abc


class StoryBoard(metaclass=abc.ABCMeta):
    """StoryBoard
    """

    def __init__(self):
        pass

    @abc.abstractmethod
    def top(self):
        pass

    @abc.abstractmethod
    def button1_pressed(self):
        pass

    @abc.abstractmethod
    def button1_released(self):
        pass

    @abc.abstractmethod
    def button2_pressed(self):
        pass

    @abc.abstractmethod
    def button2_released(self):
        pass

menu

target.sh


/app
├─ menu.py
└─ story_board.py

Menu control

menu.py


"""app/menu.py
"""

from story_board import StoryBoard


class Menu(StoryBoard):
    """Menu
    """

    def __init__(self, app):
        super().__init__()

        self.app = app
        self.lcd = app.lcd

        self.status = None

    def top(self):
        """top
        """
        self.lcd.message(message='Menu', line=self.lcd.LINE_1)
        self.lcd.message(message='>Tashizan Hikizan', line=self.lcd.LINE_2)
        self.status = 'addition'

    def button1_pressed(self):
        """button1_pressed
        """
        if self.status == 'addition':
            self.lcd.message(message='Tashizan>Hiki Zan', line=self.lcd.LINE_2)
            self.status = 'subtraction'
        else:
            self.lcd.message(message='>Tashizan Hikizan', line=self.lcd.LINE_2)
            self.status = 'addition'

    def button1_released(self):
        """button1_released
        """
        print('>>> button1_released')

    def button2_pressed(self):
        """button2_pressed
        """
        if self.status == 'addition':
            self.app.status = 'addition'
        else:
            self.app.status = 'subtraction'
        self.app.display.get(self.app.status).top()

    def button2_released(self):
        """button2_released
        """
        print('>>> button2_released')

addition

target.sh


/app
├─ addition.py
└─ story_board.py

Addition control

addition.py


"""app/addition.py
"""

from random import randint

from story_board import StoryBoard


class Addition(StoryBoard):
    """Addition
    """
    MAXIMUM = 5

    def __init__(self, app):
        super().__init__()

        self.app = app
        self.lcd = app.lcd

        self.question = 0
        self.num1 = 0
        self.num2 = 0

    def top(self):
        """top
        """
        self.question = 0
        self.num1 = 0
        self.num2 = 0
        self.lcd.message(message='Addition game^o^', line=self.lcd.LINE_1)
        self.lcd.message(message='Kimiha Wakaru Kana?', line=self.lcd.LINE_2)

    def button1_pressed(self):
        """button1_pressed
        """
        self.question = self.question + 1

        if self.question > 10:
            self.app.status = 'menu'
            self.app.display.get(self.app.status).top()
            return

        self.num1 = randint(1, self.MAXIMUM)
        self.num2 = randint(1, self.MAXIMUM)

        self.lcd.message(message='Q{}) {} + {} = ?'.format(str(self.question).zfill(2), self.num1,
                                                           self.num2), line=self.lcd.LINE_1)
        self.lcd.message(message='Kotae)', line=self.lcd.LINE_2)

    def button1_released(self):
        """button1_released
        """
        print('>>> button1_released')

    def button2_pressed(self):
        """button2_pressed
        """
        if self.num1 == 0 or self.num2 == 0:
            return
        self.lcd.message(message='Kotae) {}'.format(
            self.num1+self.num2), line=self.lcd.LINE_2)

    def button2_released(self):
        """button2_released
        """
        print('>>> button2_released')

subtraction

target.sh


/app
├─ story_board.py
└─ subtraction.py

Subtraction control

subtraction.py


"""app/subtraction.py
"""

from random import randint

from story_board import StoryBoard


class Subtraction(StoryBoard):
    """Subtraction
    """
    MAXIMUM = 5

    def __init__(self, app):
        super().__init__()

        self.app = app
        self.lcd = app.lcd

        self.question = 0
        self.num1 = 0
        self.num2 = 0

    def top(self):
        """top
        """
        self.question = 0
        self.num1 = 0
        self.num2 = 0
        self.lcd.message(message='Hiki Zan Game^o^', line=self.lcd.LINE_1)
        self.lcd.message(message='Kimiha Wakaru Kana?', line=self.lcd.LINE_2)

    def button1_pressed(self):
        """button1_pressed
        """
        self.question = self.question + 1

        if self.question > 10:
            self.app.status = 'menu'
            self.app.display.get(self.app.status).top()
            return

        self.num1 = randint(1, self.MAXIMUM)
        self.num2 = randint(1, self.MAXIMUM)
        if self.num1 < self.num2:
            temp = self.num1
            self.num1 = self.num2
            self.num2 = temp

        self.lcd.message(message='Q{}) {} - {} = ?'.format(str(self.question).zfill(2), self.num1,
                                                           self.num2), line=self.lcd.LINE_1)
        self.lcd.message(message='Kotae)', line=self.lcd.LINE_2)

    def button1_released(self):
        """button1_released
        """
        print('>>> button1_released')

    def button2_pressed(self):
        """button2_pressed
        """
        if self.num1 == 0 or self.num2 == 0:
            return
        self.lcd.message(message='Kotae) {}'.format(
            self.num1-self.num2), line=self.lcd.LINE_2)

    def button2_released(self):
        """button2_released
        """
        print('>>> button2_released')

Recommended Posts

Create an LCD (16x2) game with Raspberry Pi and Python
Ubuntu 20.04 on raspberry pi 4 with OpenCV and use with python
Use vl53l0x with Raspberry Pi (python)
Install Python 2.7.9 and Python 3.4.x with pip.
Create a web surveillance camera with Raspberry Pi and OpenCV
Python beginner opens and closes interlocking camera with Raspberry Pi
Create an Excel file with Python3
Sugoroku game and addition game with python
[Note] Using 16x2-digit character LCD (1602A) from Python with Raspberry Pi
Pet monitoring with Rekognition and Raspberry pi
Quickly create an excel file with Python #python
Create and decrypt Caesar cipher with python
[Python] Quickly create an API with Flask
Create an English word app with python
Operate an oscilloscope with a Raspberry Pi
Join an online judge with Python 3.x
Create a car meter with raspberry pi
Working with GPS on Raspberry Pi 3 Python
Create a socket with an Ethernet interface (eth0, eth1) (Linux, C, Raspberry Pi)
RabbitMQ message notification app in Python with Growl ~ with Raspberry Pi and Julius ~
Raspberry Pi 3 x Julius (reading file and grammar file)
Discord bot with python raspberry pi zero with [Notes]
Create an app that guesses students with python
[Python] Make a game with Pyxel-Use an editor-
I tried L-Chika with Raspberry Pi 4 (Python edition)
MQTT RC car with Arduino and Raspberry Pi
Create an image with characters in python (Japanese)
Use Majoca Iris elongated LCD with Raspberry Pi
Get CPU information of Raspberry Pi with Python
Get temperature and humidity with DHT11 and Raspberry Pi
Create an API server quickly with Python + Falcon
Connect to MySQL with Python on Raspberry Pi
GPS tracking with Raspberry Pi 4B + BU-353S4 (Python)
Measure CPU temperature of Raspberry Pi with Python
I got an error when I put opencv in python3 with Raspberry Pi [Remedy]
Quickly create an environment where you can play with Raspberry Pi 4 (target 1 hour)
Creating a temperature control system with Raspberry Pi and ESP32 (3) Recipient Python file
GPGPU with Raspberry Pi
DigitalSignage with Raspberry Pi
Record temperature and humidity with systemd on Raspberry Pi
Create an animated GIF local server with Python + Flask
Machine learning with Raspberry Pi 4 and Coral USB Accelerator
Easy IoT to start with Raspberry Pi and MESH
[Blender x Python] How to create an original object
Try debugging Python on Raspberry Pi with Visual Studio.
Detect mask wearing status with OpenCV and Raspberry Pi
Let's make a simple game with Python 3 and iPhone
Measure temperature and humidity with Raspberry Pi3 and visualize with Ambient
Make an umbrella reminder with Raspberry Pi Zero W
Install pyenv on Raspberry Pi and version control Python
Getting Started with Yocto Project with Raspberry Pi 4 and WSL2
Troubleshoot with installing OpenCV on Raspberry Pi and capturing
Display USB camera video with Python OpenCV with Raspberry Pi
Let's operate GPIO of Raspberry Pi with Python CGI
Raspberry Pi with Elixir, which is cooler than Python
Easy introduction to home hack with Raspberry Pi and discord.py
Programming with Python and Tkinter
x86 compiler self-made with python
Encryption and decryption with Python
Update Python for Raspberry Pi to 3.7 or later with pyenv
Word Count with Apache Spark and python (Mac OS X)