【ラズパイ入門】1602 LCDモジュールに任意の文字列を表示する方法【Python】

「Raspberry Pi」はLinuxOS相当のOS上でブラウザ操作やプログラミングが直接可能でありながら、汎用入出力(GPIO)ピンを標準搭載しているため「センサー系」「駆動系」との接続、制御が容易に可能なコンピュータです。

以下2つの記事では、GPIOピンを活用した事例として、LED素子を点滅させる方法や赤外線信号を受信する方法を紹介しました。今回は1602 LCDモジュールを、市販のI2C変換モジュールを介して、「Raspberry Pi」と接続し、任意の文字列をディスプレイ表示する方法を紹介したいと思います。1602 LCDモジュールは、最大16×2行分の文字列を表示することができる液晶ディスプレイで、ディスプレイ表示付きのガジェット作成や、「Raspberry Pi」上で動作させているプログラムの実行結果やデバッグ情報出力に活用できます。

関連記事

「Raspberry Pi」はLinuxOS相当のOS上でブラウザ操作やプログラミングが直接可能でありながら、汎用入出力(GPIO)ピンを標準搭載しているため「センサー系」「駆動系」との接続、制御が容易に可能なコンピュータです。 その[…]

eye_catch

 

関連記事

「Raspberry Pi」はLinuxOS相当のOS上でブラウザ操作やプログラミングが直接可能でありながら、汎用入出力(GPIO)ピンを標準搭載しているため「センサー系」「駆動系」との接続、制御が容易に可能なコンピュータです。 こち[…]

「Raspberry Pi」は以下の記事をもとに、OSのインストールと環境設定されていることを前提としています。
関連記事

この記事では、Raspberry Piの購入後に実施する以下の2点について、書いています。 1. OS(Raspbian)インストール 2. 初期セットアップ この記事は以下のような方向けのものになります。 Raspberr[…]

raspberry-pi-initial-set-up

 

関連記事

この記事では、Raspberry Pi 3 MODEL Bを対象に、ロボット製作に適した開発環境のセットアップ手順を紹介します。 このセットアップ手順を実行することで、以下の記事で紹介したようなロボット用のプログラミングが可能になりま[…]

make-jupyter-notebook
※本記事には「python-smbus」のインストール(3-1章)と「I2C機能」の有効化・設定(4章)が最低限必要になります。その他の設定は必須ではない認識ですが、省略した上で本記事で紹介するスクリプトが正常に動作するかは未検証です。
広告

 

動作確認済み環境


開発マシン: Raspberry Pi 3 MODEL B
OS: Raspbian Buster with desktop(Release date: 2019-09-26)
プログラミング言語: python2(version=2.7.16) or python3(version=3.7.3)

 

用意するもの


(必須)
・Raspberry Pi本体 × 1個
・ブレッドボード × 1個
・1602 LCD ディスプレイモジュール × 1個
・1602 LCD ブラック IIC/ I2C / TWI/SPI シリアル インタフェース ボード モジュール(以降は「I2CシリアルIFモジュール」と呼称) × 1個
・ジャンパワイヤ(オスーメス) × 4本
※この記事で紹介する方法では、「Raspberry Pi本体」と「ブレッドボード 」以外は、「Kuman 35個 電子工作入門キット ラズベリーパイ」という商品に同梱されているものを使用しています。
「Kuman 35個 電子工作入門キット ラズベリーパイ」では、「1602 LCD ディスプレイモジュール」と「I2CシリアルIFモジュール」は溶接された状態で梱包されています。
ジャンパワイヤ(オスーメス)が手元にない場合は、ジャンパワイヤ(オスーオス)とジャンパワイヤ(オスーメス)を組み合わせて作成することができます。

 

配線方法


  1. 「Raspberry Pi」の5V出力ピン(5V)を、「I2CシリアルIFモジュール」の「VCC」端子に接続する。
  2. 「Raspberry Pi」のGPIO2ピン(I2C_SDA1)を、「I2CシリアルIFモジュール」の「SDA」端子に接続する。
  3. 「Raspberry Pi」のGPIO3ピン(I2C_SCL1)を、「I2CシリアルIFモジュール」の「SCL」端子に接続する。
  4. 「Raspberry Pi」のグラウンド(GND)を、「I2CシリアルIFモジュール」の「GND」端子に接続する。
「I2CシリアルIFモジュール」の端子は、上から「GND」「VCC」「SDA」「SCL」と並んでいます。
「Raspberry Pi」のGPIO2、GPIO3ピンは、I2C通信の
「SDA」「SCL」端子として使用します。

 

(設計図)

lcd_module_circuit

 

 

(実際の配線イメージ)

lcd_module_circuit_image_1

※実際には、「I2CシリアルIFモジュール」の端子をブレッドボードに直に刺して、ジャンパワイヤで中継させています。
端子を直に刺すことで、以下のようにディスプレイを自立させることができます。

lcd_module_circuit_image_2

「VCC」「GND」端子を接続すると、ディスプレイのバックライトが付き「■■■■■■■■」と表示されます。3.3V出力に接続した場合は、バックライトは付きますが、何も表示されません。

(Raspberry Pi 3のピン配置)

GPIO

広告

 

プログラミング


①I2Cバス、I2Cアドレスの確認

①-1. 「I2C Tools」のインストール

sudo apt-get install -y i2c-tools

①-2. 接続されているI2Cバスを確認

sudo i2cdetect -y {I2C_BUS}

{I2C_BUS}は、通常「0」もしくは「1」を指定します。「Error: …」と表示されなければ、{I2C_BUS}番のI2Cバスが接続されている状態です。

①-3. I2Cアドレスを確認

> 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: -- -- -- -- -- -- -- --

①-2のコマンド実行時に出力される数字が有効なI2Cアドレスです。全ての出力が「–」の場合は、配線間違えや、断線の疑いがあります。

 

②Hello World!!

(Pythonスクリプト)

# -*- coding: utf-8 -*-
#!/usr/bin/python
import smbus
import time
# I2C通信の設定
I2C_ADDR = 0x27 # I2Cアドレス
LCD_WIDTH = 16 # 表示文字数の上限
LCD_CHR = 1 # 文字列送信モードの識別子
LCD_CMD = 0 # コマンド送信モードの識別子
LCD_LINE_1 = 0x80 # 一行目に表示する文字列の書き込み先
LCD_LINE_2 = 0xC0 # 二行目に表示する文字列の書き込み先
LCD_BACKLIGHT = 0x08 # バックライトをOFFにするコマンド
bus = smbus.SMBus(1) # 接続されているバスの番号を指定
def init_display():
send_byte_to_data_pin(0x33,LCD_CMD)
send_byte_to_data_pin(0x32,LCD_CMD)
send_byte_to_data_pin(0x06,LCD_CMD)
send_byte_to_data_pin(0x0C,LCD_CMD)
send_byte_to_data_pin(0x28,LCD_CMD)
send_byte_to_data_pin(0x01,LCD_CMD)
time.sleep(0.0005)
def send_byte_to_data_pin(bits, mode):
upper_bits = mode | (bits & 0xF0) | LCD_BACKLIGHT
lower_bits = mode | ((bits<<4) & 0xF0) | LCD_BACKLIGHT
bus.write_byte(I2C_ADDR, upper_bits)
enable_toggle_button(upper_bits)
bus.write_byte(I2C_ADDR, lower_bits)
enable_toggle_button(lower_bits)
def enable_toggle_button(bits):
time.sleep(0.0005)
bus.write_byte(I2C_ADDR, (bits | 0b00000100))
time.sleep(0.0005)
bus.write_byte(I2C_ADDR,(bits & ~0b00000100))
time.sleep(0.0005)
def send_string_to_display(message,line):
message = message.ljust(LCD_WIDTH," ")
send_byte_to_data_pin(line, LCD_CMD)
for i in range(LCD_WIDTH):
send_byte_to_data_pin(ord(message[i]),LCD_CHR)
# メイン処理
def main():
# LCDのメモリ初期化
init_display()
# LCDに表示する文字列のメモリへの書き込み
send_string_to_display("Hello World!!" , LCD_LINE_1) # 一行目
send_string_to_display("", LCD_LINE_2) # 二行目
time.sleep(10)
try:
main()
except Exception:
pass
finally:
LCD_BACKLIGHT = 0x00 # バックライトをOFFにするコマンド
send_byte_to_data_pin(0x01, LCD_CMD) # LCDの表示内容をクリア

(実行コマンド)

python3 display_hellow_world.py

・6行目から45行目は、「I2CシリアルIFモジュール」の設定、およびLCDモジュールへの表示文字列orコマンドの送信部分に当たります。8行目の「I2C_ADDR」には上記①-3で確認したアドレスを、31行目の「smbus.SMBus」には上記①-2で確認した有効なバスの番号を設定します。スクリプト内で指定している各種アドレスとコマンドは、データシートが見つからなかったため、サンプルコードのものをそのまま使用していますが、正常に動作しているため、設定に間違いはない認識です。
・ディスプレイの表示内容は、main関数のlcd_string関数に渡す文字列に応じて変更されます。lcd_string関数の第一引数に「表示させたい文字列」、第二引数にディスプレイの行数に対応したアドレスを指定します。
「I2C_ADDR」には、「0x27」もしくは「0x3f」を指定します。「I2CシリアルIFモジュール」に搭載されているICチップの型番によって、I2Cアドレスのデフォルト値が異なるため、正常に動作しない場合は、この値を変更してください。

(実行結果)

hello_world

広告

 

③デジタル時計

(Pythonスクリプト)

# -*- coding: utf-8 -*-
#!/usr/bin/python
import smbus
import time
# I2C通信の設定
I2C_ADDR = 0x27 # I2Cアドレス
LCD_WIDTH = 16 # 表示文字数の上限
LCD_CHR = 1 # 文字列送信モードの識別子
LCD_CMD = 0 # コマンド送信モードの識別子
LCD_LINE_1 = 0x80 # 一行目に表示する文字列の書き込み先
LCD_LINE_2 = 0xC0 # 二行目に表示する文字列の書き込み先
LCD_BACKLIGHT = 0x08 # バックライトをOFFにするコマンド
bus = smbus.SMBus(1) # 接続されているバスの番号を指定
def init_display():
send_byte_to_data_pin(0x33,LCD_CMD)
send_byte_to_data_pin(0x32,LCD_CMD)
send_byte_to_data_pin(0x06,LCD_CMD)
send_byte_to_data_pin(0x0C,LCD_CMD)
send_byte_to_data_pin(0x28,LCD_CMD)
send_byte_to_data_pin(0x01,LCD_CMD)
time.sleep(0.0005)
def send_byte_to_data_pin(bits, mode):
upper_bits = mode | (bits & 0xF0) | LCD_BACKLIGHT
lower_bits = mode | ((bits<<4) & 0xF0) | LCD_BACKLIGHT
bus.write_byte(I2C_ADDR, upper_bits)
enable_toggle_button(upper_bits)
bus.write_byte(I2C_ADDR, lower_bits)
enable_toggle_button(lower_bits)
def enable_toggle_button(bits):
time.sleep(0.0005)
bus.write_byte(I2C_ADDR, (bits | 0b00000100))
time.sleep(0.0005)
bus.write_byte(I2C_ADDR,(bits & ~0b00000100))
time.sleep(0.0005)
def send_string_to_display(message,line):
message = message.ljust(LCD_WIDTH," ")
send_byte_to_data_pin(line, LCD_CMD)
for i in range(LCD_WIDTH):
send_byte_to_data_pin(ord(message[i]),LCD_CHR)
# メイン処理
def main():
# LCDのメモリ初期化
init_display()
# [Ctrl+C]で強制終了するまで無限ループ
while True:
# 現在時刻の取得
local_time = datetime.datetime.now()
# LCDに表示する文字列のメモリへの書き込み
send_string_to_display(time.strftime("%Y.%m.%d (%a)", time.gmtime()) , LCD_LINE_1) # 一行目
send_string_to_display(local_time.strftime("%H:%M:%S"), LCD_LINE_2) # 二行目
time.sleep(0.1)
try:
print('Start:' + str(datetime.datetime.now()))
main()
except KeyboardInterrupt:
pass
finally:
LCD_BACKLIGHT = 0x00 # バックライトをOFFにするコマンド
send_byte_to_data_pin(0x01, LCD_CMD) # LCDの表示内容をクリア

(実行コマンド)

python3 display_degital_clock.py

・main関数の無限ループ内で、現在時刻を0.1秒間隔で「python」の「datetime」パッケージで取得し、lcd_string関数に文字列として渡すことで、ディスプレイ表示を実現しています。

(実行結果)※電波式の時計と2~3秒程度の誤差で時刻が表示できているので、実用上は問題なさそうです。

degital_clock

 

関連記事


赤外線リモコンで押されたボタンに応じて、表示内容を切り替えることも可能です。詳細は以下の記事をご覧ください。
関連記事

この記事では、以前に紹介した ・1602 LCDモジュールに任意の文字列を表示する方法 ・赤外線リモコンのボタンを識別する方法 を組み合わせて、1602 LCDモジュールをマルチモニター化する方法を紹介します。 赤外線リモコンの[…]

また、Raspberry Pi と市販のデバイスを組み合わせて、遠隔操作ロボットを作成した際の記事も以前に投稿しています。興味のある方はこちらもご覧ください。
関連記事

先日公開した記事ではロボット本体の組み立て方法について紹介しました。 この記事では組み立てたロボットを動作させるソフトウェアのプログラミング方法について紹介します。 開発環境は以下の通りです。 開発・制御用コンピュータ[…]

develop-robot-apps-env
広告