マイクロビット(e_21)LCD 1602 16文字2行
LCD 1602
micro:bitでI2C通信で制御できる16文字×2行液晶のLCD 1602 ディスプレイモジュールを使ってみました。データーの送信のやり方が分からずに悩んだので記載します。※以下、LCD 1602と略記します。
外観・接続
以下が16文字×2行、液晶ディスプレイモジュールのLCD 1602の外観です。
以下は実体接続の写真です。
LCD 1602を5Vで動作させるので別途電源が必要です。レベルコンバータ経由でI2C接続するだけです。そのため、接続図などは省きました。
※電源を入れて何も見えないようなら可変抵抗でコントラストを調整すると良いかも知れません。文字が出ず、私はしばらく悩んでました。
文字を表示させた状態の写真です。ここまでできるようにしようと思います。
送信データの形式
初期設定(リセット)の方法は分かったのですが、データの送信が上手くいきませんでした。データシートなどをいろいろ調べましたが・・。やっと参考になるサイト「https://ameblo.jp/pta55/entry-12686594585.html」を見つけました。
LCD 1602 モジュールはHD44780互換4bitモードらしいです。まとめると以下のようになるようです。
8bitのコマンドやデータを上下の4bitで送信する4bitモードを使います。上下の4bitデータの下位4bitに各々「BL|E|R/W|RS」のデータを付加して送信します。
コマンド送信の場合はRS=0、データ(文字データ)送信の場合はRS=1にセットします。
E(Enable)が「1>>0」でLCDにデータが書き込まれます。そのため付加データのEのbitを1を付加したデータ、続けてEのbitを0を付加したデータを送信します。
結局、8bit(1byte)のデータを送信するには下図のように4回送信することになります。
※BL:バックライト、RS:レジスタセレクション、R/W:Read/Write
スクリプト
送信の方法が分かったので、LCD 1602に文字を表示するスクリプトをどうにか作成して見ました。※コマンドデータ等の詳細はデーターシートなどを参照ください。
#!/usr/bin/env python
# -*- coding: utf-8 -*-
from microbit import *
# device address LCDのスレーブアドレス
adr_lcd=0x3f
# i2c write 1byteごとに書込みします
def lcd_wr(dat):
buf = bytearray(1)
buf[0] = dat
i2c.write(adr_lcd,buf)
sleep(2)
# BL|EN|R/W|RS cmd RS=0、data RS=1
# 送信データ化 下方で個別に説明します。(1)送信データ
def lcd_dat(dat,RS=0):
f= (dat & 0xf0)|0x0C|RS
s= (dat & 0xf0)|0x08|RS
return f,s
# コマンド送信
def lcd_cmd(dat):
f,s=lcd_dat(dat) # 上位4bitだけを使うのでそのままでよい
#print(hex(dat),f,s)
lcd_wr(f)
lcd_wr(s)
f,s=lcd_dat(dat<<4) # 下位4bitを使うのでシフト
#print(hex(dat),f,s)
lcd_wr(f)
lcd_wr(s)
# 初期化 下方で個別に説明します。(2)初期化
def lcd_init():
# function_initilize 4bit
fset=[0x30,0x30,0x30,0x20]
for c in fset:
f,s=lcd_dat(c)
print(hex(f),hex(s))
lcd_wr(f)
lcd_wr(s)
# 4bit init set data
# 28:4bit col2,disp-cur,blink,entry-increase,disp-clear
bset=[0x28,0x0F,0x06,0x01]
for c in bset:
f,s=lcd_dat(c)
print(hex(f),hex(s))
lcd_wr(f)
lcd_wr(s)
f,s=lcd_dat(c<<4)
print(hex(f),hex(s))
lcd_wr(f)
lcd_wr(s)
# # データ送信 moji data
def lcd_chr(dat):
#RS=1
f,s=lcd_dat(dat,RS=1) # データ送信なのでRS=1にする。他はコマンド送信と同じ
#print(hex(dat),f,s)
lcd_wr(f)
lcd_wr(s)
f,s=lcd_dat(dat<<4,RS=1)
#print(hex(dat),f,s)
lcd_wr(f)
lcd_wr(s)
#***** カーソル位置
def lcd_pos(x, y):
pos=(0x80 | (y* 0x40 + x))
lcd_cmd(pos)
#***** lcd に文字を表示 2行16文字
def lcd_print(pr):
n=len(pr)
#print(n)
for i in range(n):
print(pr[i])
lcd_chr(ord(pr[i]))
# 実行内容
# lcd に文字を表示
lcd_init() #LCDの初期化4bit-interface
lcd_cmd(0x01) #クリア
lcd_pos(0,0) #文字位置(0,0)
moj='0123456789012345' #文字データ
lcd_print(moj) #文字表示
lcd_pos(0, 1)
moj='!#$%&()=~|@+*<>*' #文字データ
lcd_print(moj) #文字表示
実行結果
>>> %Run mb_i2c_1602_00b.py
>>>
以下のように無事に文字が表示されました。
個別説明
作成したスクリプトの部分的な説明を記載しておきます。
(1)送信データ
先に説明した上下の4bitデータtに「BL|E|R/W|RS」のデータを付加する部分です。
# BL|EN|R/W|RS
# コマンドの送信RS=0がデフォルト、データ送信はRS=1セットが必要
def lcd_dat(dat,RS=0):
f= (dat & 0xf0)|0x0C|RS
s= (dat & 0xf0)|0x08|RS
return f,s
例
コマンド画面off(0x08)を送る場合には
(0b000010000&0b11110000)|0b00001100|0b00000000=0b00001100=0x0c=12
(0b000010000&0b11110000)|0b00001000|0b00000000=0b00001000=0x08=8
なので
コマンド画面off(0x08)の送信は0x0c >> 0x08が送信データになります。
(2)初期化
先ず4bitモードにリセットする必要があります。
LCD 1602 モジュールを4bitインターフェースモードにするには電源投入後に
0x30>>0x30>>0x30 function set 8bit を3回送信(説明書に書いてある)
0x20 function set 4bit ここで4bitに設定される
を送る必要があります。
その後、行数、カーソル、エントリーモード、クリアのコマンドを送ります。
0x28 function set 4bitモードで2行表示
0x0C または 0x0F display on Cursor表示、点滅
0x06 entry mode increment
0x01 display clear
その他
home、左右のシフトなど他にもコマンドがあります。下に記載しておきます。先のスクリプトに追加しても良いかも知れません。
#---------------------個別の関数
#***** 画面クリア
def lcd_clear():
lcd_cmd(0x01)
#***** 画面home
def lcd_home():
lcd_cmd(0x02)
#***** 画面表示On
def lcd_on():
lcd_cmd(0x0C)
#***** 画面表示Off
def lcd_off():
lcd_cmd(0x08)
#***** カーソル点滅
def lcd_blink():
lcd_cmd(0x0F)
#***** 左シフト
def lcd_lsh(self):
lcd_cmd(0x18)
#***** 右シフト
def lcd_rsh(self):
lcd_cmd(0x1C)
まとめ
micro:bitでLCD 1602 ディスプレイモジュールに文字を表示することができました。