Raspberry Pi Python I2C LCD1602表示テスト
2017.6.13 JH7UBC
今回表示テストをしたのは、I2C専用のLCD1602ではなく、一般的なLCD1602(コントローラーにHITACHIのHD44780または互換のICが使用されている)に、シリアルパラレルインターフェースを付加してI2Cで使用できるようにしているものです。
LCD1602は、Amazonで購入したSODIAL LCD1602、I2C・8ビットパラレルインターフェースもAmazonで購入したEasy
Word Mallのものです。
それぞれをドッキングさせて使用します。下の写真は、LCD1602本体にインターフェースを取り付けた様子です。
このインターフェースモジュールには、PHILIPSのPCF8574が使われていて、回路は、下図のとおりです。(私が調べて描きました。メーカーが保証しているものではありませんのでご注意ください。)
まず、I2C・パラレルインターフェースのI2Cアドレスを調べます。
Raspberry PiでI2C通信を可能にして(メニュー→設定→Raspberry Piの設定→インターフェースと進み、I2Cを有効にします。)
Raspberry Piのコマンドモードで、sudo i2cdetect -y 1を入力します。
このインターフェースのI2Cアドレスが、0x27であることが分かります。
回路図のA0,A1,A2のジャンパーで、0x20〜0x27までのアドレスが設定可能です。
今回は、デフォルトの0x27で使用します。
Raspberry Pi Pythonで、I2Cを利用するためには、まずsmbusをimportしてから
smbus.SMBus(busnumber)でコネクションオブジェクトを取得します。
このsmbusライブラリで、I2Cにデータを送出する関数は、いくつかありますが、
今回は、1バイトの単独書き込み関数 write_byte_data(アドレス,コマンド,データ)を使います。
どのような信号がI2Cに送出されるのか観察するために
bus.write_byte_data(0x27,0x00,ox12)を連続的に実行して、出力をpicoscopeで見てみました。
アドレス(アドレス+書き込みなら0)、コマンド、データの順にMSBファーストでシリアルに送出されることが分かります。
コマンドとデータは、ACKでシフトレジスタからラッチされPCF8574のI/Oポートに出力されます。
回路図のようにLCD1602は、4ビットモードで使用することにして、
PCF8574のI/OポートのP4〜P7は、LCDのDB4〜DB7に接続されています。
また、I/Oポートの下位4ビットは、それぞれ
P0=RS(Register Select)
P1=R/W(Read/Wriye)
P2=E(Enable)
P3=BL(Back Light)
に接続されています。
LCD1602の書き込みタイミングをマニュアルで見るとデータが有効になった後、Enableが1から0になる立下りで
LCDにデータが書き込まれます。
そこで、1バイトのデータを書き込むために、RS=0,R/W=0,BL=1として、
コマンド書き込みのタイミングで、E=1とし、データ書き込みのタイミングで、E=0とします。
例えば、8ビットモードを与えるコマンド0X30を書き込む場合は、
LCD_addr=0x27
LCD_EN=0b00000100
LCD_BL=0b00001000
data=0x30として
bus.write_byte_data(LCD_addr,(data | LCD_EN | LCD_BL),(data |LCD_BL))でデータを送ると
上位4ビットデータにEnableとBackLightのデータが加えられ、LCD1602にデータが書き込まれ、バックライトが点灯します。
(実際には、4ビットモードで上位4ビット、下位4ビットの書き込みを行っています。)
次に、Raspberry PiとI2Cモジュール付きLCDの接続について説明します。
Raspberry PiからのI2C信号は、3.3Vですが、モジュール付のLCD1602は、LCDコントロールIC HD44780の供給電圧が
5Vのため、レベル変換モジュールを間に入れることにしました。
使ったのは、秋月電子のFXMA2102モジュールを使用しました。
このモジュールには、プルアップ抵抗がついていません。Rspberry PiのI2CポートとI2Cシリアルパラレルモジュールには、
それぞれプルアップ抵抗が内蔵されていますので、プルアップ抵抗なしのモジュールを選択しました。
実験回路の回路図です。
テストに使用したスクリプトです。
""" I2C LCD1602 test use PCF8574 I2C pararel interface 2017.6.12 JH7UBC Keiji Hata """ # -*- coding:utf-8 -*- from time import sleep import smbus #PCF8574 LCD1602 connection #P0 = LCD RS #P1 = LCD R/W #P2 = LCD E #P3 = LCD BackLight #P4 = LCD DB4 #P5 = LCD DB5 #P6 = LCD DB6 #P7 = LCD DB7 bus = smbus.SMBus(1) LCD_addr = 0x27 LCD_EN = 0b0000100#LCD Enable LCD_BL = 0b0001000#LCD BackLight LCD_CMD = 0x00#command mode LCD_CHR = 0x01#character mode LCD_CHARS = 16 LCD_LINE1 = 0x80#Line1 top address LCD_LINE2 = 0xC0#Line2 top address def LCD_write(bits,mode): #High 4bits data = (bits & 0xF0) | mode bus.write_byte_data(LCD_addr,(data | LCD_EN | LCD_BL),(data | LCD_BL)) sleep(0.0001)#wait 100us #Low 4bits data = ((bits << 4) & 0xF0) | mode bus.write_byte_data(LCD_addr,(data | LCD_EN | LCD_BL),(data | LCD_BL)) sleep(0.0001)#wait 100us def LCD_init(): LCD_write(0x33,LCD_CMD) LCD_write(0x32,LCD_CMD) LCD_write(0x06,LCD_CMD) LCD_write(0x0C,LCD_CMD) LCD_write(0x28,LCD_CMD) LCD_write(0x01,LCD_CMD) sleep(0.001) def LCD_text(message,line): message = message.ljust(LCD_CHARS," ") LCD_write(line,LCD_CMD) for i in range(LCD_CHARS): LCD_write(ord(message[i]),LCD_CHR) def main(): while True: LCD_text("Hello World!",LCD_LINE1) LCD_text("JH7UBC",LCD_LINE2) sleep(3) LCD_text("ABCDEFGHIJKLMNOP",LCD_LINE1) LCD_text("1234567890123456",LCD_LINE2) sleep(3) try: LCD_init() main() except KeyboardInterrupt: pass |
実験の様子です。Hello World! JH7UBCとABCDEFGHIJKLMNOP 1234567890123456が3秒ごとに交互に表示されます。