PICOでI2CキャラクターLCDを使う

概要

 以前、Arduino UNO R3 で使用したI2CキャラクターLCDをRaspberry Pi Pico でも使いたくなり、検証しました。Aruduino開発環境でプログラム作成したかったのですが、どうしてもI2C接続できなくて、諦めました。今回、MycroPython(Thonnyという開発環境)で作成しています。

配線接続

 PICOとLCDの接続図を載せます。



 実際の接続した状況の写真を載せます。

LCDコントロールプログラム

 UART経由で受信したフレーズをLCDに表示するプログラムです。コマンド ‘LCD1602’,’LCD2004’を受信した場合、LCD表示は行わず、表示対象のLCDを切り替えます。
 過去、4回の受信フレーズを、表示文字制限内で表示します。

from machine import Pin, I2C, UART
from utime import sleep
import time

u_ch = [0,0,1]                                                     # UART設定(チャンネル,TX,RX)
g_n = [[0,1],[4,5],[8,9],[12,13],[16,17],[20,21]]                  # I2C0対象ポート 0~5
s_n = 3                                                            # I2C0対象ポート 3→[12,13]

LCD_ADRS = [0x50,0x3F]                                             # LCD-I2Cアドレス( ACM1602NI-FLW-FBW-M01 , ACM2004D-FLW-FBW-IIC )
LCD_SPEC = [[16,2],[20,4]]                                         # LCD表示文字数定義
LCD_INIT = [b'\x01',b'\x38',b'\x0C',b'\x06']                       # LCD初期化(b'\x0C'ディスプレイOFF,カーソルOFF , b'\x0F':ディスプレイON,カーソルON)
LCD_LINE = [b'\x80',b'\xC0',b'\x94',b'\xD4']                       # LCD各行先頭位置(1~4)

_SET_CMD = const(0x00)                                             # LCDコマンド実行
_SET_DAT = const(0x40)                                             # LCDデータ設定

def write_word(adr,data):
    if(type(data)!='bytearray'):
        buf=bytearray(data)
        i2c.writeto(adr,buf)
    else:
        i2c.writeto(adr,data)

def send_command(adr,cmd):
    write_word(adr,bytearray([0x00,cmd]))

def send_data(adr,data):
    write_word(adr,bytearray([0x80,data]))


uart = UART(u_ch[0],baudrate=9600,tx=Pin(u_ch[1]),rx=Pin(u_ch[2])) # uart0 設定(外部接続用)
i2c = I2C(0,scl=Pin(g_n[s_n][1]),sda=Pin(g_n[s_n][0]),freq=50000)  # i2c0 設定

#接続LCDデバイス検出・検出LCDデバイス初期化
for addr in i2c.scan():
    print("IIC LCD ADRS : {:x}".format(addr))
    for order in LCD_INIT:
        i2c.writeto_mem( addr , _SET_CMD , order )
        sleep(0.01)   

#UART0経由でLCD表示データ受信待ち
LCD_TGT=1                                                          # 対象LCD選択( ACM1602NI-FLW-FBW-M01 , ACM2004D-FLW-FBW-IIC )
LCD_DATA=['','','','']                                             # 受信LCD表示データ
while(True):
    buf=bytes()
    LCD_DATA[0]=''
    
    #データ受信
    while(True):
        if(uart.any()>0):
            buf=uart.read(1)
            if(buf==b'\r'):
                break
            elif(buf[0]>0x1F and buf[0]<0x7f):
                LCD_DATA[0]+=buf.decode()
                time.sleep(0.0001)
    
    #受信データあり
    if(LCD_DATA[0]!=''):
        if(LCD_DATA[0]=='LCD1602'):
            LCD_TGT=0
        elif(LCD_DATA[0]=='LCD2004'):
            LCD_TGT=1
        else:
            print(LCD_DATA[0])
            i2c.writeto_mem(LCD_ADRS[LCD_TGT],_SET_CMD,b'\x01')       # 画面消去
            time.sleep(0.4)
        
            #LCDデータ転送
            lin_no=0
            for dat in LCD_DATA:
                v_lin=[dat[i:i+LCD_SPEC[LCD_TGT][0]] for i in range(0,len(dat),LCD_SPEC[LCD_TGT][0])]
            
                for tmp in v_lin:
                    if(lin_no<LCD_SPEC[LCD_TGT][1]):
                        i2c.writeto_mem(LCD_ADRS[LCD_TGT],_SET_CMD,LCD_LINE[lin_no])   # 各行先頭にカーソル移動
        
                        for char in tmp:
                            if(LCD_TGT==0):
                                send_data(LCD_ADRS[LCD_TGT],ord(char))                 # 16X2 LCDデバイス表示
                            else:
                                i2c.writeto_mem(LCD_ADRS[LCD_TGT],_SET_DAT,char)       # 20X4 LCDデバイス表示
                    
                            time.sleep(0.001)
                    lin_no+=1
        
            for idx in range(3):
                LCD_DATA[3-idx] = LCD_DATA[2-idx]
        
      

表示データ送信プログラム

 外部のPICOから短いフレーズを順番に送信するテストプログラムです。全フレーズを送信するとLCDを切り替えます。
 こちらは、ARDUINO IDEで作成しています。

int lcd_num=0;

char* myStrings1[]={
  "Hello!",
  "Good Morning.",
  "Thank you very much.",
  "How do you do?",
  "What time is it now?",
  "Hello. How are you doing?",
  "Long time no see. How have you been?",
  "Have you seen any interesting movies lately?",
  "What do you do in your free time?",
  "I would like to leave my luggage.",
  "Nice to meet you. It is a pleasure to meet you.",
  "Do you have any questions or concerns so far?",
};

char* myStrings2[]={
  "Hello!",
  "Good Morning.",
  "Thank you.",
  "How do you do?",
  "What time?",
  "How are you?",
  "Long time no see.",
  "Good evening.",
  "Sounds good.",
  "Not too bad.",
  "Fine.",
  "Have a nice day.",
};


void setup() {
  Serial.begin(9600);
  Serial1.setTX(0);
  Serial1.setRX(1);
  Serial1.begin(9600);
  delay(500);
}
void loop() {
  if (lcd_num==0){
    lcd_num=1;
    Serial1.println("LCD1602");
  }else{
    lcd_num=0;
    Serial1.println("LCD2004");
  }
  delay(2000);

  for (int i = 0; i < 12; i++){
    Serial.println(myStrings2[i]);
    Serial1.println(myStrings2[i]);
    delay(2000);
  }
}

まとめ

 ARDUINO開発環境で作成出来なかったのは残念ですが、思ったものに近いものは出来ました。