[ラズパイ] LCD1602をI2C接続し日本語(カナ)を表示させる

 最近、注文した部品が立て続けに届き始めたかな。たぶん即位礼正殿の儀が終わって、税関の流れがスムーズになったせいかなと勝手に思ってるw。


 上のキットにはLCD1602(LEDバックライト付…後から知った)が入っている。

 単品購入だとこのあたりと思う。しかし、この商品、I2Cにつなげるためのシリアルインターフェイスがついていない。I2Cでなくてもつなげることはできるけど、何か、結構大変そうだし、いかんせん情報が古い。やっぱしI2Cでつなげたい。

 I2Cのインターフェースボードを別途購入する必要がありそう。安いやつは、中国・台湾発送なので忘れるぐらい遅いから注意してね(20日はかかる)。急ぎなら、国内発送のものを注文したほうがいいね(何回も言ってるけどw)。あと、セットのもあるからそっちのほうが手っ取り早いかも。迷わず、中華・台湾発送をポチるww

 下調べで見つけた上のサイトを見ると・・5VのI2Cをラズパイに直結やないかーいww。まぁ、こういうサイトは結構あって、結果動けばいいんだけど、複数デバイスをI2Cにつないだ場合の動作不良とかラズパイ本体が不安。LCDのI2Cインターフェースは、ほとんどがArduino対応品の5Vなので、ラズパイのI2Cにつなげるには3.3Vの双方向のロジックレベルコンバータを挟むのがセオリーとのことでアマゾンを捜索。

 早速購入も相変わらず安さにつられ、中華・台湾発送をポチリ待ちぼうけを食らうw。でもいいんです!LCDはキットに入ってたし、136円+360円/5個 = 208円で遊べるんだからっ

 上のサイトをよく読んで接続。このロジックレベルコンバーターは4チャンネルだけど、今回はI2CでSCA、SDLの2線のみなので、5V側HV3とHV4にシリアルインターフェイスのSCA、SDLをつないで3.3V側のLV3、LV4から対応するSCA、SDLをラズパイにつなぐ。HVには5V、LVには3.3Vの電源をつないでGNDを取り廻せば完成。

 でもこれ、ほんとに3.3Vと5Vを変換してるんでしょうか?w。確認にはオシロスコープしかないと思うんですが、持ってないんでわかりません。購入したらチェックしてみますけど、信じて次行きますwww

 LCD1602とシリアルインターフェースは半田でつけたかったけど、すでに両方ともにピンヘッダがついていたので外すのも面倒だったからブレッドボードで結線した。LCD1602の表面の傷防止フィルムがついたままという貧乏臭さは許してください。で、配線を確認してラズパイ電源オン!!

 とりあえず、LCDのバックライトが光りました。この時点で初めてバックライト付きだと気づきますw。で、I2Cをつないだ時の儀式を行います

user@computer:$ i2cdetect -y 1

 そいで、ちゃんと認識されているかを確認します。0x27で認識しているようです。このシリアルインターフェースのI2Cアドレスは0x27と0x3fの2パターンがあります。今回は0x27でした。とりあえず、なんでもいいんで最初に文字を表示させたいですね。

上のサイトも接続が・・・5V-I2C直結ですが・・・、まぁいいとして・・w、参考としてテストプログラムをダウンロードしてみます。0x27なので

user@computer:$ wget http://osoyoo.com/driver/i2clcda.py

ちなみに0x3fの場合は

user@computer:$ wget http://osoyoo.com/driver/i2clcdb.py

 ターミナル開いた時のカレントフォルダにダウンロードされてしまうので、デスクトップに任意のフォルダでも作って、そこでターミナルを開くか移動して上のコマンドを実行しましょう。i2clcda.pyができるので、ThonnyでもMuでもいいから開いて実行してみましょう。

動画のように交互表示されればOK。見えないときはシリアルインターフェースにある濃度調整の可変抵抗を回してみよう。

次に、自分の好きな文字を簡単に表示させるお手軽なライブラリをさがす(オイw)。

こんなん見つかったので、早速導入。LCD.pyのみをダウンロードしてもいいだろうし、任意のディレクトリで

user@computer:$ git clone https://github.com/sterlingbeason/LCD-1602-I2C

でクローンして、どこでもいいのでLCD.pyをインポートしてやればいいと思う。下の例は./LCD1602I2C/LCD.pyをインポートした例。


# ./LCD1602I2C/LCD.pyのインポート
from LCD1602I2C.LCD import LCD
import time

lcd = LCD(2,0x27,True)

lcd.message("Hello World!", 1)
lcd.message("ANDROIPHONE!!", 2)

time.sleep(5)
lcd.clear()

 このライブラリは外人さんが作ったので日本語には対応していない。カタカナを入れても文字化けやら正常に表示できない。これを解決するのに参考にしたのが下のサイト。

 このサイトを参考に、LCD.pyのLCDクラスのmessageメソッドを若干改造する。ついでに全角・半角カナどちらでもOK、表示できない文字の場合は塗りつぶし表示という仕様にした。とりあえずmessageメソッド純正コードと日本語に対応させたjmessageメソッドを掲載します。

 jmessageメソッドを実装するにあたり、codesのコード列がズレてた部分があった(LCD1602の種類差なのかも…)ので修正している(不躾ながらコメントに連絡させていただいた所、訂正して頂いたようです)。このcodesは半角カナ、全角数字に対応してないので前処理用に半角・全角変換のライブラリmojimojiをインストールしておく必要がある。

user@computer:$ sudo pip3 install mojimoji

でインストール後、「import mojimoji」で使えるようになる。

def message(self, string, line = 1):
    # display message string on LCD line 1 or 2
    if line == 1:
        lcd_line = self.LCD_LINE_1
    elif line == 2:
        lcd_line = self.LCD_LINE_2
    else:
        raise ValueError('line number must be 1 or 2')

    string = string.ljust(self.LCD_WIDTH," ")

    self.lcd_byte(lcd_line, self.LCD_CMD)

    for i in range(self.LCD_WIDTH):
        self.lcd_byte(ord(string[i]), self.LCD_CHR)
    def jmessage(self, string, line = 1):
        
        #文字コードnの文字 = n番目の文字
        codes = u'線線線線線線線線線線線線線線線線                !"#$%&\'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}→←                                 。「」、・ヲァィゥェォャュョッーアイウエオカキクケコサシスセソタチツテトナニヌネノハヒフヘホマミムメモヤユヨラリルレロワン゛゜αäβεμσρq√陰ι×¢£nöpqθ∞ΩüΣπxν千万円÷ 塗'
        #変換する文字の辞書(ex.「バ」=「ハ」「゛」)
        dic ={u'ガ':u'カ゛',u'ギ':u'キ゛',u'グ':u'ク゛',u'ゲ':u'ケ゛',u'ゴ':u'コ゛',u'ザ':u'サ゛',u'ジ':u'シ゛',u'ズ':u'ス゛',u'ゼ':u'セ゛',u'ゾ':u'ソ゛',u'ダ':u'タ゛',u'ヂ':u'チ゛',u'ヅ':u'ツ゛',u'デ':u'テ゛',u'ド':u'ト゛',u'バ':u'ハ゛',u'ビ':u'ヒ゛',u'ブ':u'フ゛',u'ベ':u'ヘ゛',u'ボ':u'ホ゛',u'パ':u'ハ゜',u'ピ':u'ヒ゜',u'プ':u'フ゜',u'ペ':u'ヘ゜',u'ポ':u'ホ゜',u'℃':u'゜C'}
        
        # display message string on LCD line 1 or 2
        if line == 1:
            lcd_line = self.LCD_LINE_1
        elif line == 2:
            lcd_line = self.LCD_LINE_2
        else:
            raise ValueError('line number must be 1 or 2')

        string = string.ljust(self.LCD_WIDTH," ")

        self.lcd_byte(lcd_line, self.LCD_CMD)

                
        # 半角カナのみ全角へ
        string = mojimoji.han_to_zen(string, ascii=False, digit=False)
        # 全角数字のみ半角へ
        string = mojimoji.zen_to_han(string, ascii=False, kana=False)

        # for i in range(self.LCD_WIDTH):
        #     self.lcd_byte(ord(string[i]), self.LCD_CHR)
        #濁音など、文字の変換        
        string2 = ""
        for i in range(self.LCD_WIDTH):
            if ( string[i] in dic.keys() ):
                string2 += dic[string[i]]
            else:
                string2 += string[i]
        
        #文字コードのリストにある文字なら表示、それ以外は塗りつぶし
        for i in range(self.LCD_WIDTH):
            if (codes.find(string2[i]) >= 0):
                self.lcd_byte(codes.find(string2[i])+1,self.LCD_CHR)
            elif (string2[i] == u' '):
                self.lcd_byte(0x10,self.LCD_CHR)
            else:
                self.lcd_byte(0xFF,self.LCD_CHR)

 jmessageメソッドをLCD.pyに付け加えてmojimojiインポート・インストールをして、以下のコードを実行。LCD1602I2CmodのフォルダにLCD.pyを改変したものを入れておいてある。

from LCD1602I2Cmod.LCD import LCD
import time

lcd = LCD(2,0x27,True)
lcd.jmessage("ヨウコソ!!2千円!!",1)
lcd.jmessage("アンドロイフォン",2)

time.sleep(5)

lcd.clear()

「千」「円」とかは、コード表にある文字なので使える(参考サイトにコード表があるので参考にされたし)。全角半角カナ、全角数字も表示で来ているようなので、良しとした。ハイエナ的コード感があるけど、参考にしたサイト様には感謝です。

後日・・・・

なんか、ライブラリのLCD.pyを、直いじりはやっぱり気になってしょうがないので、LCDを継承したJLCD.pyを作り、messageメソッドをオーバーライドしときました。基本ハイエナは変わってませんが…w

JLCD.py

import mojimoji
from LCD1602I2C.LCD import LCD

class JLCD(LCD):
    
    # message method override
    def message(self, string, line = 1):
        
        #文字コードnの文字 = n番目の文字
        codes = u'線線線線線線線線線線線線線線線線                !"#$%&\'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}→←                                 。「」、・ヲァィゥェォャュョッーアイウエオカキクケコサシスセソタチツテトナニヌネノハヒフヘホマミムメモヤユヨラリルレロワン゛゜αäβεμσρq√陰ι×¢£nöpqθ∞ΩüΣπxν千万円÷ 塗'
        #変換する文字の辞書(ex.「バ」=「ハ」「゛」)
        dic ={u'ガ':u'カ゛',u'ギ':u'キ゛',u'グ':u'ク゛',u'ゲ':u'ケ゛',u'ゴ':u'コ゛',u'ザ':u'サ゛',u'ジ':u'シ゛',u'ズ':u'ス゛',u'ゼ':u'セ゛',u'ゾ':u'ソ゛',u'ダ':u'タ゛',u'ヂ':u'チ゛',u'ヅ':u'ツ゛',u'デ':u'テ゛',u'ド':u'ト゛',u'バ':u'ハ゛',u'ビ':u'ヒ゛',u'ブ':u'フ゛',u'ベ':u'ヘ゛',u'ボ':u'ホ゛',u'パ':u'ハ゜',u'ピ':u'ヒ゜',u'プ':u'フ゜',u'ペ':u'ヘ゜',u'ポ':u'ホ゜',u'℃':u'゜C'}
        
        # display message string on LCD line 1 or 2
        if line == 1:
            lcd_line = self.LCD_LINE_1
        elif line == 2:
            lcd_line = self.LCD_LINE_2
        else:
            raise ValueError('line number must be 1 or 2')

        string = string.ljust(self.LCD_WIDTH," ")

        self.lcd_byte(lcd_line, self.LCD_CMD)

                
        # 半角カナのみ全角へ
        string = mojimoji.han_to_zen(string, ascii=False, digit=False)
        # 全角数字のみ半角へ
        string = mojimoji.zen_to_han(string, ascii=False, kana=False)

        # for i in range(self.LCD_WIDTH):
        #     self.lcd_byte(ord(string[i]), self.LCD_CHR)
        #濁音など、文字の変換        
        string2 = ""
        for i in range(self.LCD_WIDTH):
            if ( string[i] in dic.keys() ):
                string2 += dic[string[i]]
            else:
                string2 += string[i]
        
        #文字コードのリストにある文字なら表示、それ以外は表示しない
        for i in range(self.LCD_WIDTH):
            if (codes.find(string2[i]) >= 0):
                self.lcd_byte(codes.find(string2[i])+1,self.LCD_CHR)
            elif (string2[i] == u' '):
                self.lcd_byte(0x10,self.LCD_CHR)
            else:
                self.lcd_byte(0xFF,self.LCD_CHR)

lcdtest.py

# from LCD1602I2Cmod.LCD import LCD
from JLCD import JLCD as LCD
import time

lcd = LCD(2,0x27,True)
lcd.message("ヨウコソ!!",1)
lcd.message("アンドロイフォン",2)

time.sleep(5)
lcd.clear()

これで、LCDクラスと同じように使えて日本語が表示できるようになった。

 

 

2 thoughts on “[ラズパイ] LCD1602をI2C接続し日本語(カナ)を表示させる

Comments are closed.