「Raspberry Pi」はLinuxOS相当のOS上でブラウザ操作やプログラミングが直接可能でありながら、汎用入出力(GPIO)ピンを標準搭載しているため「センサー系」「駆動系」との接続、制御が容易に可能なコンピュータです。
以下2つの記事では、GPIOピンを活用した事例として、LED素子を点滅させる方法や赤外線信号を受信する方法を紹介しました。今回は1602 LCDモジュールを、市販のI2C変換モジュールを介して、「Raspberry Pi」と接続し、任意の文字列をディスプレイ表示する方法を紹介したいと思います。1602 LCDモジュールは、最大16×2行分の文字列を表示することができる液晶ディスプレイで、ディスプレイ表示付きのガジェット作成や、「Raspberry Pi」上で動作させているプログラムの実行結果やデバッグ情報出力に活用できます。
「Raspberry Pi」はLinuxOS相当のOS上でブラウザ操作やプログラミングが直接可能でありながら、汎用入出力(GPIO)ピンを標準搭載しているため「センサー系」「駆動系」との接続、制御が容易に可能なコンピュータです。 その[…]
「Raspberry Pi」はLinuxOS相当のOS上でブラウザ操作やプログラミングが直接可能でありながら、汎用入出力(GPIO)ピンを標準搭載しているため「センサー系」「駆動系」との接続、制御が容易に可能なコンピュータです。 こち[…]
この記事では、Raspberry Piの購入後に実施する以下の2点について、書いています。 1. OS(Raspbian)インストール 2. 初期セットアップ この記事は以下のような方向けのものになります。 Raspberr[…]
この記事では、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)
用意するもの
・ブレッドボード × 1個
・1602 LCD ディスプレイモジュール × 1個
・1602 LCD ブラック IIC/ I2C / TWI/SPI シリアル インタフェース ボード モジュール(以降は「I2CシリアルIFモジュール」と呼称) × 1個
・ジャンパワイヤ(オスーメス) × 4本
※この記事で紹介する方法では、「Raspberry Pi本体」と「ブレッドボード 」以外は、「Kuman 35個 電子工作入門キット ラズベリーパイ」という商品に同梱されているものを使用しています。
「Kuman 35個 電子工作入門キット ラズベリーパイ」では、「1602 LCD ディスプレイモジュール」と「I2CシリアルIFモジュール」は溶接された状態で梱包されています。
Physical Computing Lab
Raspberry Pi3 Model B ボード&ケースセット 3ple Decker対応 (Clear)-Physical Computing Lab
TSI-P031-Clear
配線方法
- 「Raspberry Pi」の5V出力ピン(5V)を、「I2CシリアルIFモジュール」の「VCC」端子に接続する。
- 「Raspberry Pi」のGPIO2ピン(I2C_SDA1)を、「I2CシリアルIFモジュール」の「SDA」端子に接続する。
- 「Raspberry Pi」のGPIO3ピン(I2C_SCL1)を、「I2CシリアルIFモジュール」の「SCL」端子に接続する。
- 「Raspberry Pi」のグラウンド(GND)を、「I2CシリアルIFモジュール」の「GND」端子に接続する。
「Raspberry Pi」のGPIO2、GPIO3ピンは、I2C通信の「SDA」「SCL」端子として使用します。
(設計図)
(実際の配線イメージ)
※実際には、「I2CシリアルIFモジュール」の端子をブレッドボードに直に刺して、ジャンパワイヤで中継させています。
端子を直に刺すことで、以下のようにディスプレイを自立させることができます。
(Raspberry Pi 3のピン配置)
プログラミング
①I2Cバス、I2Cアドレスの確認
①-1. 「I2C Tools」のインストール
sudo apt-get install -y i2c-tools |
①-2. 接続されているI2Cバスを確認
sudo i2cdetect -y {I2C_BUS} |
①-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: -- -- -- -- -- -- -- -- |
②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 |
・ディスプレイの表示内容は、main関数のlcd_string関数に渡す文字列に応じて変更されます。lcd_string関数の第一引数に「表示させたい文字列」、第二引数にディスプレイの行数に対応したアドレスを指定します。
(実行結果)
③デジタル時計
(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 |
(実行結果)※電波式の時計と2~3秒程度の誤差で時刻が表示できているので、実用上は問題なさそうです。
関連記事
この記事では、以前に紹介した ・1602 LCDモジュールに任意の文字列を表示する方法 ・赤外線リモコンのボタンを識別する方法 を組み合わせて、1602 LCDモジュールをマルチモニター化する方法を紹介します。 赤外線リモコンの[…]
先日公開した記事ではロボット本体の組み立て方法について紹介しました。 この記事では組み立てたロボットを動作させるソフトウェアのプログラミング方法について紹介します。 開発環境は以下の通りです。 開発・制御用コンピュータ[…]