ラズパイでLCDを制御してハローワールドを表示する。
使用ライブラリはpigpio
i2c接続するLCDはosoyoo製の物を使うが、たぶん他社製品でも似たようなもの
とりあえずpythonで実行してみる
プログラムを実行する前にpigpiodの起動を忘れないこと
$ sudo pigpiod
サンプルコード
製品ページ
のwgetコマンドはosoyoocomとなっていて、「.」が抜けているので
追加しないとエラーになります
マニュアル
osoyooのマニュアルがどこにあるのかわからなかったので
似たような製品を秋月で調べて参考にしました
サンプルコードを参考にpigpioで動くように改変
import time import pigpio # pigpioのインポート I2C_ADDR = 0x3f # i2cアドレス i2cdetect -y 1 とかで調べておく LCD_WIDTH = 16 # 表示文字数 LCD_BACKLIGHT = 0x08 # 00001000 バックライトの点灯 ENABLE = 0b00000100 # 書き込みを可能にするビット?よくわからん LCD_CHR = 1 # データ送信モード LCD_CMD = 0 # コマンド送信モード LCD_LINE_1 = 0x80 # 1-Lineアドレス(上段) LCD_LINE_2 = 0xC0 # 2-Lineアドレス(下段) # タイミング調整用の定数 E_PULSE = 0.0005 E_DELAY = 0.0005 # pigpio初期設定 pi = pigpio.pi() lcd = pi.i2c_open(1, I2C_ADDR, 0) # 「ハロー ワールド!」表示用の配列 # 文字コードはマニュアル参照 hello = [202, 219, 176, 32, 220, 176, 217, 196, 222, 33] def lcd_init(): # LCDの初期設定 lcd_byte(0x33,LCD_CMD) # 110011 lcd_byte(0x32,LCD_CMD) # 110010 lcd_byte(0x06,LCD_CMD) # 000110 カーソルの移動方向 lcd_byte(0x0C,LCD_CMD) # 001100 ディスプレイ ON, カーソル OFF lcd_byte(0x28,LCD_CMD) # 101000 lcd_byte(0x01,LCD_CMD) # 000001 ディスプレイのクリア time.sleep(E_DELAY) def lcd_byte(bits, mode): # データ書き込み bits_high = mode | (bits & 0xF0) | LCD_BACKLIGHT bits_low = mode | ((bits<<4) & 0xF0) | LCD_BACKLIGHT # 上位ビット pi.i2c_write_byte(lcd, bits_high) lcd_toggle_enable(bits_high) # 下位ビット pi.i2c_write_byte(lcd, bits_low) lcd_toggle_enable(bits_low) def lcd_toggle_enable(bits): time.sleep(E_DELAY) pi.i2c_write_byte(lcd, (bits | ENABLE)) time.sleep(E_PULSE) pi.i2c_write_byte(lcd, (bits & ~ENABLE)) time.sleep(E_DELAY) def lcd_string(message,line): message = message.ljust(LCD_WIDTH," ") lcd_byte(line, LCD_CMD) for i in range(LCD_WIDTH): lcd_byte(ord(message[i]),LCD_CHR) def lcd_jp(line): # 日本語表示用 lcd_byte(line, LCD_CMD) for i in hello: lcd_byte(i, LCD_CHR) def main(): lcd_init() while True: lcd_string("Hello!",LCD_LINE_1) lcd_string("World!",LCD_LINE_2) time.sleep(3) lcd_jp(LCD_LINE_1) lcd_jp(LCD_LINE_2) time.sleep(3) if __name__ == '__main__': try: main() except KeyboardInterrupt: pass finally: lcd_byte(0x01, LCD_CMD)
実行すると
Hello! World! 3秒後 ハロー ワールド! ハロー ワールド! 3秒後 以降ループ
と、LCDに表示される
送信データの制御について
LCD1602のデータシートにはi2c通信についてほとんど記載が無いので
どのようにデータを制御しているのか分かりませんでした
なのでサンプルコードとにらめっこして考えた結果
おそらく下記のようになると思います (推測です)
i2c制御フォーマット (S,A,Pは省略)
15 | 14 | 13 | 12 | 11 | 10 | 9 | 8 | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
S7 | S6 | S5 | S4 | S3 | S2 | S1 | S0 | D7 | D6 | D5 | D4 | BL | EN | RW | MO |
S7 | S6 | S5 | S4 | S3 | S2 | S1 | S0 | D3 | D2 | D1 | D0 | BL | EN | RW | MO |
8 - 15 : スレーブアドレス用
0 - 7 : コマンド、データ書き込み用ビット
D4 - D7 : 上位ビット
D0 - D3 : 下位ビット
BL : バックライトのON(1)、OFF(0)
EN : 書き込みの有効(1)、無効(0)
RW : 読み込み(1)、書き込み(0)
MO : データ送信モード(1)、コマンド送信モード(0)
LCDへ書き込むためにはENの書き込み有効化したあと無効化する必要があり
上位ビットを書き込んだあとに下位ビットを書き込む必要がある
つまり、最低4回書き込むことになる
サンプルコードではEN有効を書き込む前にEN無効を書き込んでいるので
計6回書き込んでいる(必要があるのかどうかはわからない)
例、 1-Line(上段)にAを書き込む場合
# 表示するラインを設定 10001100 # 1-Line(0x80)の上位ビットを書き込み有効 # 140 10001000 # 1-Line(0x80)の上位ビットを書き込み無効 # 136 00001100 # 1-Line(0x80)の下位ビットを書き込み有効 # 12 00001000 # 1-Line(0x80)の下位ビットを書き込み無効 # 8 # 表示する文字を送信 01001101 # A(01000001)の上位ビットを書き込み有効 # 77 01001001 # A(01000001)の上位ビットを書き込み無効 # 73 00011101 # A(01000001)の下位ビットを書き込み有効 # 29 00011001 # A(01000001)の下位ビットを書き込み無効 # 25
自分で考えてこうなるのでは?と思っているだけなので
合っているかどうかはわかりません
思った通りの表示はしているので大丈夫だと思いますが参考程度に
教訓
サンプルコードを改変して表示させるのが楽