LCD 1602A をRaspberryPiで使う

## 1602Aとは
電子工作キットとかに良く入っている(らしい)
ちっちゃい表示器。[LCD](https://amzn.to/3ku7RVl)と呼ばれるもの。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1023362/ff5804c0-4d43-1ec3-1b66-be0ad675ef74.png)

こんなやつ

## 使い方  
[I2Cシリアルインターフェイス](https://amzn.to/3suR1Zj)がついているという事を前提に進める
(I2Cがついていない場合は、はんだ付けとかして付けた方が良い)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1023362/a1de8aa8-ce7e-4e90-3b27-c6b45f4a75db.png)

こんなやつ

### I2C有効化
[ここが参考になる](https://www.qoosky.io/techs/2316d68b2e)

### 接続  

* VCC - pin2(5Vならどこでも良い)
* GND - pin39(GNDならどこでも良い)
* SDA - pin2
* SCL - pin3  
  
**※上記はGPIOピンの番号**
![raspberrypi-gpio-04.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1023362/cae38691-ffe8-e0cd-f8e2-545b74e924f6.png)

### コード
[参考サイト](https://www.raspberrypi-spy.co.uk/2015/05/using-an-i2c-enabled-lcd-screen-with-the-raspberry-pi/)のコードを少しいじってみた

```sample.py
  
from LCD_1602A import LCD

lcd = LCD()
lcd.show_message("Hello World",1)
lcd.show_message("Good Night Japan",2)
input()
```
https://github.com/box16/LCD_1602A

`show_message`の第一引数に表示させたい文字(今のところ英数字のみ)、第二引数に表示させる列(1602Aの場合は1行目か2行目か)

`input`はただ待ってるだけ
(デストラクタによって画面がクリアされるようにしているため)
(何かしら待つ処理が無いと一瞬文字が表示されて終わるだけ)

```LCD_1602A.py
import smbus
import time

MAX_WIDTH = 16

ENABLE = 0x04

BYTE_TYPE = {"data": 1,
             "command": 0, }

LINE_ADDRESS = {"1": 0x80,
                "2": 0xC0, }

BACKLIGHT_SWITCH = {"on": 0x08,
                    "off": 0x00, }

TIMING = {"pulse": 0.0005,
          "delay": 0.0005, }


class LCD:

    def __init__(self, i2c_address=0x27, i2c_detect_number=1):
        self.i2c_address = i2c_address
        self.bus = smbus.SMBus(i2c_detect_number)
        self.init_lcd()

    def __del__(self):
        self.init_lcd()

    def init_lcd(self):
        self._send_byte(0x33, BYTE_TYPE["command"])
        self._send_byte(0x32, BYTE_TYPE["command"])
        self._send_byte(0x06, BYTE_TYPE["command"])
        self._send_byte(0x0C, BYTE_TYPE["command"])
        self._send_byte(0x28, BYTE_TYPE["command"])
        self._send_byte(0x01, BYTE_TYPE["command"])
        time.sleep(TIMING["delay"])

    def show_message(self, message, line):
        if (line == 1) or (line == 2):
            show_line = LINE_ADDRESS[str(line)]
        else:
            show_line = LINE_ADDRESS["1"]
        self._send_byte(show_line, BYTE_TYPE["command"])

        message = message.ljust(MAX_WIDTH, " ")
        for i in range(MAX_WIDTH):
            self._send_byte(ord(message[i]), BYTE_TYPE["data"])

    def _send_byte(self, _bytes, mode):
        bits_high = mode | (_bytes & 0xF0) | BACKLIGHT_SWITCH["on"]
        self.bus.write_byte(self.i2c_address, bits_high)
        self._enable_lcd(bits_high)

        bits_low = mode | ((_bytes << 4) & 0xF0) | BACKLIGHT_SWITCH["on"]
        self.bus.write_byte(self.i2c_address, bits_low)
        self._enable_lcd(bits_low)

    def _enable_lcd(self, bits):
        time.sleep(TIMING["delay"])
        self.bus.write_byte(self.i2c_address, (bits | ENABLE))
        time.sleep(TIMING["pulse"])
        self.bus.write_byte(self.i2c_address, (bits & ~ENABLE))
        time.sleep(TIMING["delay"])
```

もし、日本語を表示させたいなら
`self._send_byte(ord(message[i]), BYTE_TYPE["data"])`ここら辺の仕組みを考え直すことになりそう

### 文字が表示されない!!とき
I2Cシリアルインターフェイスのプラスねじ部分を回してバックライトの調整をする