MicroPython(ESP8266)を使用して、I2Cで接続できるキャラクターLCDの表示を行ってみたいと思います。
使用したLCDは、Z8S180でも使用した「KKHMF DC 5V 1602 LCD ディスプレイモジュール 16×2キャラクタ LCDブルーブラックライト」と「EasyWordMall 1602 LCD ブラック IIC/I2C/TWI/SPI シリアル インタフェース ボード モジュール」です。(amazon等で購入)
ただ、上記キャラクターLCDは5V仕様なので、3.3V仕様のESP-WROOM-02とは直接に接続することができません。そこで今回はI2Cレベル変換モジュールPCA9306(AE-PCA9306)(秋月電子)を使用しました。
回路図は下記のとおりです。
thonnyとシリアル通信するためには、回路図には図示していませんが、IO15(6pin)を10KΩでGnd(プルダウン)に接続する必要があります。
および、IO2(7pin)、IO0(8pin)は内部でプルアップされていますが、必要であれば10KΩでVCC(3.3V)に接続してください。
EasyWordMall 1602 LCD ブラック IIC/I2C/TWI/SPI シリアル インタフェース ボード モジュールへの接続は、J1のコネクターで、シルク表示で GND、Vcc、SDA、SCLの順番になっています。
半固定ボリュームはLCDの輝度調整用で、真ん中あたりにしておきます。
LEDと表示されているジャンパーを抜くとバックライトが消えるようです。
I2Cインターフェイスモジュール のスレーブアドレスは、
PCF8574T では、0x27
PCF8574ATでは、0x3fとなるようです。
アマゾンのレビューをみると2種類のデバイスが出荷されているよう
なのでついているデバイスの確認が必要です。
(ともに A0/A1/A2がオープンの時)
今回購入したものは、PCF8574Tで、0x27 となっていますので以下スレーブアドレスは、0x27の設定となっています。
MicroPythonのプログラムは下記のようになりました。
開発環境は前回の「MicroPython(ESP8266)に萌えたい。ESP-WROOM-02でLちか。」を参照してください。
まずは、I2Cのpinを決めます。ESP8266ではソフトウェアI2Cになっているので、任意のpinを指定できます。
ここでは、SCL=IO14(3pin)、SDA=IO12(4pin)に設定しました。
必要な、ライブラリーとI2Cの初期を行います。
LCDのI2Cアドレスは前記の通り、0x27です。
from machine import Pin, I2C
import utime
i2c=I2C(scl=Pin(14),sda=Pin(12),freq=100000)
LCD_i2c_addr= 0x27
LCD ディスプレイモジュール とI2C シリアル インタフェース ボードモジュールとは次のような接続になっています。
LCDの制御のために、RS/RW/EN/LEDの各端子のビット位置を設定します。ちなみに LCDへのデータ転送は、4BitモードになっていますのでD7~D4までの4Bitで設定します。
# lcd 1602 port
#
# D0 > RS
# D1 > R/W
# D2 > E
# D3 > LED on/off
# D4 > DB4
# D5 > DB5
# D6 > DB6
# D7 > DB7
LCDへの書き込みは4ビットごとに書き込みします。
書き込みには、コマンドデータと表示用データの書き込みの2種類があります。
モードの切り替えは RS端子で行います。
コマンドデータ >> RS=0
表示用データ >> RS=1
書き込みと読み出しのモード切替はRW端子で行います。
読み出し >> RW=1
書き込み >> RW=0
今回の場合は、読み出しは行わないので、RW端子は常に 0のままです。
実際の書き込みタイミングは、ENを正論理でパルスを送ります。
つまり、 EN >> 0>1>0のタイミングの1発だけのパルスを生成します。
バックライトは常にONにしています
パックライトON >> LED=1
バックライトOFF>> LED=0
コマンド用の4ビットの書き込みのユーザー関数プログラムは下記のようになります。
lcd4bitwriteの引数commandでコマンド用のデータを渡します。
commandは4bit左シフトし、D7~D4に渡します。
コマンドデータ用なので、RS=0、つまりD0=0とします。
論理和ORで必要なビットを1にし、論理積ANDで必要なビットのみ1を取ります。
lcd_command_buff[0]で作成したcommandをバッファに入れます。
i2c.writetoでI2Cアドレスとlcd_command_buffを指定して書き込みします。
def lcd4bitwrite(command):
command = command << 4
command = command | 0b00001000
command = command & 0b11111000
lcd_command_buff[0]= command
i2c.writeto(LCD_i2c_addr,lcd_command_buff)
command = command | 0b00001100
command = command & 0b11111100
lcd_command_buff[0]= command
i2c.writeto(LCD_i2c_addr,lcd_command_buff)
command = command | 0b00001000
command = command & 0b11111000
lcd_command_buff[0]= command
i2c.writeto(LCD_i2c_addr,lcd_command_buff)
同様に表示用の4ビットの書き込みのプログラムは下記のようになります。
表示データ用なのでRS=1、つまりD0=1とします。
def data_lcd4bitwrite(command):
command = command << 4
command = command | 0b00001001
command = command & 0b11111001
lcd_command_buff[0]= command
i2c.writeto(LCD_i2c_addr,lcd_command_buff)
command = command | 0b00001101
command = command & 0b11111101
lcd_command_buff[0]= command
i2c.writeto(LCD_i2c_addr,lcd_command_buff)
command = command | 0b00001001
command = command & 0b11111001
lcd_command_buff[0]= command
i2c.writeto(LCD_i2c_addr,lcd_command_buff)
続いて、8ビットコマンド用および8ビット表示用の関数を作成します。
8ビットなので、上位4ビット下位4ビットの分けて4ビット用のユーザー関数で書き込みします。
def lcd8bitwrite(command):
command2 = command
command = command >> 4
lcd4bitwrite(command)
lcd4bitwrite(command2)
def data_lcd8bitwrite(command):
command2 = command
command= command >> 4
data_lcd4bitwrite(command)
data_lcd4bitwrite(command2)
LCDのイニシャライズは、作成した、 lcd4bitwrite(command)とlcd8bitwrite(command)を利用して、イニシャライズを行います。
def lcd_init():
data_set = 0x03
lcd4bitwrite(data_set)
utime.sleep_ms(5)
lcd4bitwrite(data_set)
lcd4bitwrite(data_set)
data_set = 0x02
lcd4bitwrite(data_set)
data_set = 0x28
lcd8bitwrite(data_set)
data_set = 0x0c
lcd8bitwrite(data_set)
data_set = 0x01
lcd8bitwrite(data_set)
utime.sleep_ms(2)
data_set = 0x06
lcd8bitwrite(data_set)
data_set = 0x02
lcd8bitwrite(data_set)
utime.sleep_ms(2)
メインのプログラムは、LCDのイニシャライズを行った後、messge1とmessge2を表示します。
messge1はUnicodeで書かれた文字を単語ごとに登録しています。UnicodeからASCIIに変換するのにord()関数が必要です。
messge2は、ASCIIコードを直接16進表記にして登録しています。
messge1=bytearray(16)
messge2=bytearray(16)
messge1=(' ','*','*','*','*','E','S','P','8','2','6','6','*','*','*',' ',)
# messge2 = Hello I2C World
messge2=(0x20,0x48,0x65,0x6c,0x6c,0x6f,0x20,0x49,0x32,0x43,0x20,0x57,0x6f,0x72,0x6c,0x64,)
lcd_init()
for i in range(0, 16):
data_lcd8bitwrite(ord(messge1[i]))
data_set = 0xc0
lcd8bitwrite(data_set)
for i in range(0, 16):
data_lcd8bitwrite(messge2[i])
LCDには、下記のように表示されます。
****ESP8266***
Hello I2C World
全体のプログラムは下記の通りです。
# MicroPython(ESP8266) I2C LCD display(KKHMF 1602 LCD +EasyWordMall 1602 LCD i2c i/F)
#
# SCL = IO14(3pin)
# SDA = IO12(4pin)
# LCD I2C address =0x27 (addr open)
#
# lcd 1602 port
#
# D0 > RS
# D1 > R/W
# D2 > E
# D3 > LED on/off
# D4 > DB4
# D5 > DB5
# D6 > DB6
# D7 > DB7
#
from machine import Pin, I2C
import utime
i2c=I2C(scl=Pin(14),sda=Pin(12),freq=100000)
LCD_i2c_addr= 0x27
lcd_command_buff=bytearray(1)
messge1=bytearray(16)
messge2=bytearray(16)
messge1=(' ','*','*','*','*','E','S','P','8','2','6','6','*','*','*',' ',)
# messge2 = Hello I2C World
messge2=(0x20,0x48,0x65,0x6c,0x6c,0x6f,0x20,0x49,0x32,0x43,0x20,0x57,0x6f,0x72,0x6c,0x64,)
def lcd_init():
data_set = 0x03
lcd4bitwrite(data_set)
utime.sleep_ms(5)
lcd4bitwrite(data_set)
lcd4bitwrite(data_set)
data_set = 0x02
lcd4bitwrite(data_set)
data_set = 0x28
lcd8bitwrite(data_set)
data_set = 0x0c
lcd8bitwrite(data_set)
data_set = 0x01
lcd8bitwrite(data_set)
utime.sleep_ms(2)
data_set = 0x06
lcd8bitwrite(data_set)
data_set = 0x02
lcd8bitwrite(data_set)
utime.sleep_ms(2)
def lcd4bitwrite(command):
command = command << 4
command = command | 0b00001000
command = command & 0b11111000
lcd_command_buff[0]= command
i2c.writeto(LCD_i2c_addr,lcd_command_buff)
command = command | 0b00001100
command = command & 0b11111100
lcd_command_buff[0]= command
i2c.writeto(LCD_i2c_addr,lcd_command_buff)
command = command | 0b00001000
command = command & 0b11111000
lcd_command_buff[0]= command
i2c.writeto(LCD_i2c_addr,lcd_command_buff)
def data_lcd4bitwrite(command):
command = command << 4
command = command | 0b00001001
command = command & 0b11111001
lcd_command_buff[0]= command
i2c.writeto(LCD_i2c_addr,lcd_command_buff)
command = command | 0b00001101
command = command & 0b11111101
lcd_command_buff[0]= command
i2c.writeto(LCD_i2c_addr,lcd_command_buff)
command = command | 0b00001001
command = command & 0b11111001
lcd_command_buff[0]= command
i2c.writeto(LCD_i2c_addr,lcd_command_buff)
def lcd8bitwrite(command):
command2 = command
command = command >> 4
lcd4bitwrite(command)
lcd4bitwrite(command2)
def data_lcd8bitwrite(command):
command2 = command
command= command >> 4
data_lcd4bitwrite(command)
data_lcd4bitwrite(command2)
lcd_init()
for i in range(0, 16):
data_lcd8bitwrite(ord(messge1[i]))
data_set = 0xc0
lcd8bitwrite(data_set)
for i in range(0, 16):
data_lcd8bitwrite(messge2[i])