Raspberry Pi の安価なタッチパネルで簡単に操作できるようにする

## 概要
IoTのデモでRaspberry Piのタッチパネルで簡単な操作をしたいと思っていたところ、Amazonで安価なタッチパネルを見つけましたので、実際にアプリを試作して利用できるかどうかを検証してみました。
![R05.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/75892/2ff81134-2c05-e951-e5d8-d38a87d86ed3.png)

## 準備
今回準備したものは以下です。
・MHS-3.5inch RPi Display
　https://www.amazon.co.jp/dp/B07RZW9CWP/
・Raspberry Pi Model 3B
　https://www.amazon.co.jp/dp/B01NHEBAN5/
・16GB の microSD カード
MHS-3.5inch RPi DisplayはAmazonでケース付きが3千円を切る最安値のものを利用しました。
概要の写真のようにタッチパネルが付属のケースにしっかり収まって、安価ながら様になっています。

## 設定
先ずSDカードに最新のRasbian OSのdesktop版をインストールします。
インストールしただけでは今回のタッチパネルは使えませんので、HDMI接続のモニタか、SSH接続で作業を行えるように設定してください。（説明は割愛します。）

同梱されていた説明書の記述に従い、Gitからセットアッププログラムを入手して、実行します。

```sh
git clone https://github.com/goodtft/LCD-show.git
chmod -R 755 LCD-show
cd LCD-show/
sudo ./MHS35-show
```

再起動すると、以下の起動の様子がタッチパネルに表示されます。
![R03.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/75892/b036bdd6-c112-11a8-499d-619e915daaa5.png)

X-Window画面が起動して、タッチペンに反応するようになりました。
![R04.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/75892/13136568-36f0-fc86-904f-f9d386ba229f.png)
無論指でのタッチも可能ですが、さすがに反応がにぶくてタッチペンを常備した方が良いでしょう。

今回はタッチパネルで操作できる簡単な表示画面をPython2.7で開発するため、Tkinterをインストールします。
また、SSHでGUIの画面開発はできないので、試験用にリモートディスクトップのインストールもインストールします。

```sh
sudo apt-get install python-tk
sudo apt-get install xrdp
```

以下のように、リモートディスクトップ画面でコンソールからPythonのプログラムを起動して試験を行います。
![R01.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/75892/3c1c354e-a704-973c-b00a-dd74a2497fb9.png)

## タッチパネル用アプリの開発
今回はPythonのTkinterを利用して、タッチパネルの解像度480x320でボタン操作ができる簡単なアプリを試作しました。
簡単な試作のためコードは突っ込みどころ満載ですが、そこはご容赦を。

```test.py
#! /usr/bin/env python
# -*- coding: utf-8 -*-
import Tkinter as tk
import random
import subprocess

def update():
   val = random.random()
   label1.config(text=str(val))
   if(val > 0.5):
     text1.delete(0,tk.END)
     text1.insert(tk.END,'111')
   else:
     text1.delete(0,tk.END)
     text1.insert(tk.END,'000')

   root.after(1000, update)

def reboot():
   subprocess.call("sudo reboot", shell=True)

def end():
   subprocess.call("sudo shutdown -h now", shell=True)

# フォーム
root = tk.Tk()
root.title(u"フォーム表示試験")
root.geometry("480x280")

# ラベル
label1 = tk.Label(root, text='0')
label1.pack()

# テキストボックス
text1 = tk.Entry(root, width=3)
text1.insert(tk.END,'000')
text1.pack()

# ボタン
btn1 = tk.Button(root, text=u'終了', width=30, command=lambda: root.quit())
btn1.pack()

btn2 = tk.Button(root, text=u'再起動', width=30, command=lambda: reboot())
btn2.pack()

btn3 = tk.Button(root, text=u'電源OFF', width=30, command=lambda: end())
btn3.pack()

# タイマー
root.after(1000, update)

root.mainloop()
```

### 指定した解像度のフォームを作成

以下で指定した解像度のフォームを作成します。タッチパネルの解像度480x320ですが、Tkinterの試用でタイトルバーの40ピクセルがgeometry()で指定したサイズには含まれないため、480x280の解像度で指定しています。Tkinterはこのような妙な癖があるので注意する必要があります。

```py
root = tk.Tk()
root.title(u"フォーム表示試験")
root.geometry("480x280")

（中略）

root.mainloop()
```

### ラベルとテキストボックスにデータを表示
ラベルやテキストボックスは以下のように簡単に作成できます。

```py
# ラベル
label1 = tk.Label(root, text='0')
label1.pack()

# テキストボックス
text1 = tk.Entry(root, width=3)
text1.insert(tk.END,'000')
text1.pack()

（中略）

# タイマー
root.after(1000, update)
```

今回は1秒毎タイマー処理で乱数を発生させて乱数をラベルに表示し、乱数の値でテキストボックスの内容を変更しています。
ラベルはそのまま値をセットできますが、テキストボックスは一旦値を削除したうえで、追加する必要があり、ちょっと特殊な仕様のため注意がする必要があります。

```py
def update():
   val = random.random()
   label1.config(text=str(val))
   if(val > 0.5):
     text1.delete(0,tk.END)
     text1.insert(tk.END,'111')
   else:
     text1.delete(0,tk.END)
     text1.insert(tk.END,'000')

   root.after(1000, update)
```

### ボタンの処理
ボタンについても以下のように簡単に追加できます。
ボタンをクリックした後の処理はcommandに記述しますが、今回のようにlambdaを指定して関数を呼び出すことができます。root.quit()でTkinterで表示したフォームを閉じることができます。

```py
btn1 = tk.Button(root, text=u'終了', width=30, command=lambda: root.quit())
btn1.pack()

btn2 = tk.Button(root, text=u'再起動', width=30, command=lambda: reboot())
btn2.pack()

btn3 = tk.Button(root, text=u'電源OFF', width=30, command=lambda: end())
btn3.pack()
```

ボタンの処理で、それぞれシャットダウン、再起動をさせるようにしました。
SSHで接続してシャットダウンはIoTの現場で地味に面倒なので、タッチパネルのタッチでできると便利ですよね。

```py
def reboot():
   subprocess.call("sudo reboot", shell=True)

def end():
   subprocess.call("sudo shutdown -h now", shell=True)
```

## タッチパネル用アプリの自動起動
タッチパネル用のアプリは自動で起動させるには、X-WindowにデフォルトでログインしているユーザpiのLXDEに自動起動の設定を追加するだけです。

以下のようにフォルダを作成し、autostartファイルを追加します。

```sh
mkdir /home/pi/.config/lxsession
mkdir /home/pi/.config/lxsession/LXDE-pi
nano /home/pi/.config/lxsession/LXDE-pi/autostart
```

autostartファイルには、@の後に起動するプログラムを記述するだけです。

```
@python /home/pi/test.py
```

以上の設定を終えて再起動すると、起動後に以下のタッチパネル用アプリが自動で起動します。

![R02.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/75892/333b10a7-b405-c352-488a-c90c72c87442.png)

## まとめ
安価なタッチパネルを利用して Raspberry Pi で簡単にタッチ操作できる画面を表示することができました。
連続して使ってみてそれなりの耐久性があれば、IoTの現場でデータを表示し簡単な制御を指示するパネルの試作としては十分活用できそうです。

また、これまでは詳しくないユーザに貸し出した場合などはそのまま電源を切断してもらっていましたが、無論これはSDカードのOSイメージを壊すなどの危険性が高く、お勧めできる状態ではありませんでした。「電源OFF」のタッチパネル操作ぐらいならお願いできますので、これが使えたら安全にRaspberry Piの電源を切ってもらうことが可能になりそうです。

## 参考情報
**GitHub lcdwiki/LCD-show**
https://github.com/lcdwiki/LCD-show
**MHS-3.5inch RPi Display**
http://www.lcdwiki.com/MHS-3.5inch_RPi_Display
**備忘録：OpenCVでUSBカメラの画像を取得してTkinterで表示させてGUI起動時にアプリを自動起動させるためのメモ**
https://dreamerdream.hateblo.jp/entry/2019/11/19/120000
**Tkinter による GUI プログラミング**
https://python.keicode.com/advanced/tkinter.php
**Python tkinterウィンドウを更新する方法**
https://base64.work/so/python/1906661