Hobby Science&Experiment

愛と工作の日々

趣味でやっている工作や勉強したことのメモ書きです。

I2C液晶ディスプレイ(1602)をRaspberry Pi 3+で使用する(Python3)

前回の記事で大気中CO2濃度の取得に成功しました。しかしPCディスプレイでしか取得値を表示できないため、確認が面倒でした。常時ONの小型ディスプレイなんかで確認することが出来ると大変便利です。

f:id:tara-chang:20200422230921p:plain
前回の成果 CO2濃度計測
今回は電子工作キットに入っていた、1602 I2C液晶ディスプレイ(LCD)を利用してみたいと思います。情報収集するとラズパイ+Pythonで操作を行っている報告が見つかったので、こちらの記事の模倣で行けるのではないでしょうか。やってみたいと思います。
terutakke.com

この記事でやること

・1602 I2C液晶ディスプレイをRaspberry Pi 3+に配線する。
Raspberry Pi 3+のI2C通信を有効にする。
・現在日時をディスプレイに表示する。
・CO2センサーの取得値をディスプレイに表示する。

メモ

商品名の1602という数字は16文字×2行で32文字表示できるという意味のようです。I2C(Inter-Integrated Circuit)通信に関してはこちらの記事に詳しくまとまっています。
www.lapis-semi.com
ちなみにこのOSOYOO社のキットはサーボモーターや人感センサー、温湿度/気圧センサー、LCD、IRリモコン、リレー、ケーブル類など盛り沢山でたったの2,780円の超お得な詰め合わせになっています。バラで買うより断然安いですね。
https://www.amazon.co.jp/dp/B01M6ZFNSS/ref=cm_sw_r_tw_dp_U_x_wfsPEbPJX9189

準備するもの

・Raspberry Pi3+
・1602 I2C液晶ディスプレイ
・配線用ジャンパーケーブル
 LCD側にはメスのジャンパーケーブルが必要になります。

配線

以下の表のように配線しました。SDA、SCLのpinはラズパイには一つずつしかないので、ここに繋げば間違いなさそうです。VCCは3Vに繋いでしまうと薄っすらとしか文字が読めなくなります。

LCD ラズパイ側
GND
GND
VCC
5VO
SDA
SDA1(2pin)
SCL
SCL1(3pin)

※pinはGPIO番号です。

ラズパイの設定

ラズパイの設定画面を開き、インターフェースタブでI2C通信を有効にします。
f:id:tara-chang:20200425205232p:plain
一旦再起動した後、次のコードを入力してI2Cのアドレスを取得します。

sudo i2cdetect 1

結果

pi@raspberrypi:~ $ sudo i2cdetect 1
WARNING! This program can confuse your I2C bus, cause data loss and worse!
I will probe file /dev/i2c-1.
I will probe address range 0x03-0x77.
Continue? [Y/n] y
     0  1  2  3  4  5  6  7  8  9  a  b  c  d  e  f
00:          -- -- -- -- -- -- -- -- -- -- -- -- -- 
10: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
20: -- -- -- -- -- -- -- 27 -- -- -- -- -- -- -- -- 
30: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
40: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
50: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 

アドレスが27であることがわかりました。

日時出力プログラム

参考にしていた記事のコードをそのまま使用してみたのですが、今回のセットアップと合わない部分がありエラーが出ました。10~16行目が不要そうだったので削除して実行してみると、無事日時が出力されました。アドレスは27になっています。

# -*- coding: utf-8 -*-
#!/usr/bin/python
from time import sleep
from time import gmtime, strftime
import datetime
import smbus

# Define some device parameters
I2C_ADDR  = 0x27 # I2C device address 
LCD_WIDTH = 16   # Maximum characters per line

# Define some device constants
LCD_CHR = 1 # Mode - Sending data
LCD_CMD = 0 # Mode - Sending command

LCD_LINE_1 = 0x80 # LCD RAM address for the 1st line
LCD_LINE_2 = 0xC0 # LCD RAM address for the 2nd line

LCD_BACKLIGHT  = 0x08  # On
#LCD_BACKLIGHT = 0x00  # Off

ENABLE = 0b00000100 # Enable bit

# Timing constants
E_PULSE = 0.0005
E_DELAY = 0.0005

#Open I2C interface
#bus = smbus.SMBus(0)  # Rev 1 Pi uses 0
bus = smbus.SMBus(1) # Rev 2 Pi uses 1

def lcd_init():
  # Initialise display
  lcd_byte(0x33,LCD_CMD) # 110011 Initialise
  lcd_byte(0x32,LCD_CMD) # 110010 Initialise
  lcd_byte(0x06,LCD_CMD) # 000110 Cursor move direction
  lcd_byte(0x0C,LCD_CMD) # 001100 Display On,Cursor Off, Blink Off 
  lcd_byte(0x28,LCD_CMD) # 101000 Data length, number of lines, font size
  lcd_byte(0x01,LCD_CMD) # 000001 Clear display
  sleep(E_DELAY)

def lcd_byte(bits, mode):
  # Send byte to data pins
  # bits = the data
  # mode = 1 for data
  #        0 for command

  bits_high = mode | (bits & 0xF0) | LCD_BACKLIGHT
  bits_low = mode | ((bits<<4) & 0xF0) | LCD_BACKLIGHT

  # High bits
  bus.write_byte(I2C_ADDR, bits_high)
  lcd_toggle_enable(bits_high)

  # Low bits
  bus.write_byte(I2C_ADDR, bits_low)
  lcd_toggle_enable(bits_low)

def lcd_toggle_enable(bits):
  # Toggle enable
  sleep(E_DELAY)
  bus.write_byte(I2C_ADDR, (bits | ENABLE))
  sleep(E_PULSE)
  bus.write_byte(I2C_ADDR,(bits & ~ENABLE))
  sleep(E_DELAY)
  

def lcd_string(message,line):
  # Send string to display
  message = message.ljust(LCD_WIDTH," ")
  lcd_byte(line, LCD_CMD)
  for i in range(LCD_WIDTH):
    lcd_byte(ord(message[i]),LCD_CHR)

def main(): #「日時」を表示
    # Main program block
    # Initialise display
    lcd_init()
    while True:
      local_time = datetime.datetime.now()
      lcd_string(strftime("%Y.%m.%d (%a)", gmtime()) , LCD_LINE_1)
      lcd_string(local_time.strftime("%H:%M"), LCD_LINE_2)
      sleep(1)

      local_time = datetime.datetime.now()
      lcd_string(strftime("%Y.%m.%d (%a)", gmtime()) , LCD_LINE_1)
      lcd_string(local_time.strftime("%H %M"), LCD_LINE_2)
      sleep(1)

try:        
  print('Start:' + str(datetime.datetime.now()))
  main()
except KeyboardInterrupt:
  pass
finally:
  LCD_BACKLIGHT = 0x00  #バックライトオフ
  lcd_byte(0x01, LCD_CMD) #表示内容クリア
  GPIO.cleanup()

CO2濃度を表示する。

前回の記事の通りにMH-Z19Bを配線します。Pyhthonコードの中でライブラリを使用する場合は次のような処方が有効なのでした。

#CO2.py
import mh_z19
co2 = mh_z19.read_all()["co2"]

こちらを先ほどのコードに捻じ込むことでCO2濃度を表示します。

#変更前
lcd_string(local_time.strftime("%H:%M"), LCD_LINE_2)

#変更後
import mh_z19
co2 = mh_z19.read_all()["co2"]
lcd_string(local_time.strftime("%H:%M")+" CO2:"+str(co2)+"ppm", LCD_LINE_2)

※import文は文頭に加えています。
f:id:tara-chang:20200426174344p:plain
無事表示できました。これでPC画面を起動しなくても横目でCO2濃度を確認することが出来るようになりました!