TOPに戻る

ラズパイ2023年10月更新 bookworm ③ pipが使えない! pythonでグラフィック・ディスプレイを利用

Adafruit 2.0" 320x240 Color IPS TFT Displayを利用する

 Adafruitで入手したSPIバス接続のディスプレイをラズパイにつなぎます。

  2.0" 320x240 Color IPS TFT Display with microSD Card Breakout

 2.0インチ、320×240ピクセルのカラーTFTディスプレイで、商品名にコントローラST7789が含まれていませんが、シルクには印刷されています。裏面にメモリ・カードのソケットがついています(今回は使わない)。

 電源およびロジック電圧は3~5Vです。

 このグラフィック・ディスプレイは、SPI接続です。コントローラのST7789にはデバイス・ドライバ(/boot/overlaysのREADME参照)がありますが、表示領域が固定でこのディスプレイの1/4ほどしかなく、画面全体を利用できるpythonで利用できるライブラリを探しました。

 Adafruitラズパイ関連のpython関係のドライバなどは、相当昔に開発をやめ、CircuitPythonのサブシステム(?)上に構築するように変化しています。

 Pimoroni のST7789ライブラリが見つかりました(中身はAdafruit製?)。

  https://github.com/pimoroni/st7789-python/tree/master

 そこに書かれているインストール方法、

  sudo pip3 install st7789

ではなく、次のようにインストールしました。bookwormではPython2はなくなっています。

$ pip install st7789

 しかし、

This environment is externally managed
╰─> To install Python packages system-wide, try apt install
    python3-xyz, where xyz is the package you are trying to
    install.

    If you wish to install a non-Debian-packaged Python package,
    create a virtual environment using python3 -m venv path/to/venv.
    Then use path/to/venv/bin/python and path/to/venv/bin/pip. Make
    sure you have python3-full installed.

    For more information visit http://rptl.io/venv

note: If you believe this is a mistake, please contact your Python installation or OS distribution provider. You can override this, at the risk of breaking your Python installation or OS, by passing --break-system-packages.
hint: See PEP 668 for the detailed specification.

というメッセージが出ます。

 最初に書かれている解決方法を試します。

$ sudo apt-get install python3-st7789

を実行すると、

Reading package lists... Done
Building dependency tree... Done
Reading state information... Done
E: Unable to locate package python3-st7789

が表示されて、apt-getを最新にしても解決しません。つまり、Debianパッケージにはなっていない?ということのようです。

pythonの仮想環境

 次のメッセージを翻訳します。

「Debian パッケージ以外の Python パッケージをインストールする場合は、 python3 -m venv パスを使用して仮想環境を作成します。次に、 path/to/venv/bin/python と path/to/venv/bin/pip を使用します。」

$ python-V

Python 3.11.2

 現在、Python 3.11.2バージョンです。python3の初期のころから仮想環境は利用できるようになっていたようですが、venvが標準的な仮想環境構築に使われるようになったのはバージョン3.3以降からのようです。

 1年ほど前まで、ラズパイでpythonの仮想環境のことを意識することはありませんでした。

 venvは仮想環境を提供する機能で、各仮想環境には、それぞれ異なる種類のパッケージ、異なるバージョン
のものをインストールできるそうです。しかし、その必要性を感じない。。。いつも最新の状態に保つという使い方をしていたから。。。

 調べると、仮想環境を利用するには、

  • 作成
  • 有効化

に作業が必要です。

 何と面倒なと思いました。さらに調べると、ラズパイのbookworm は、元となったDebianの2023年6月10日をベースとしています。

 世の中、数年もしくは10年以下で、いろいろなアプリケーションが収束してしまいます。でも、それらを利用したシステムは10年以上メインテナンスをしないといけないことも多いです。したがって、装置一つに、システム丸ごと異なる2バージョンが共存するという事態が起こり、それが実現可能な時代になっています。

 bookwormでは、Python 2.xが完全になくなったことと、Python3はPEP 668に従い、pipでのパッケージ・インストールを拒否することになりました。青天の霹靂です。これが、最初の長いメッセージだったわけです。

 たぶん、bookwormで、

  • Debianディストリビューションそのもの
  • Debian Free Software Guidelines(DFSG)に準拠しているがビルド時もしくは動作時にDebianディストリビューション外のソフトウェアが必要となるもの
  • Debianディストリビューションと互換性はあるがDFSGに準拠しない

が明確に分けられましたが、それがpythonのpipを用いたインストールに影響が出たのではないかと推測。。。いろいろ混在することでトラブルが増え、問題が起こったときの解明に時間を要するというのを避けたいのかもしれません。すごく健全な方向です。

なぜか解決方法が三つある?

 検索すると、大きく三つの解決方法があるようです。

  • --break-system-packagesオプションを利用<その1>
  • 手順を踏んで標準搭載のvenvを利用<その2>
  • pipxを利用<その3>

接続

 SPIバスのインターフェースで、ラズパイとTFTディスプレイとを接続します。

TFTディスプレイ ピン番号GPIOx ピン番号 GPIOx TFTディスプレイ
D/C 15 GPIO22    
Vin 17 +3.3V    
MOSI 19 GPIO10 MOSI 20 GND GND
 - 21 GPIO9 MISO 22 GPIO25 RST
SCK 23 GPIO11 CLK 24 GPIO8 CE0 LCD CS
    25 GPIO7 CE1  -

 正統派だと思われる2番目の方法から試します。

仮想環境を作り、st7789をインストールする<その2>

 仮想環境を「作成」します。

$ python -m venv env

 7,8秒ほど時間がたってプロンプトが戻ってきました。lsを実行すると、envというディレクトリができています。

$ cd env
$ ls
bin  include  lib  lib64  pyvenv.cfg

 いくつかのディレクトリやファイルが入っています。

 「有効化」します。

yoshi@raspberrypi:~ $ source env/bin/activate
(env) yoshi@raspberrypi:~ $

 有効化されました。プロンプトが変化して明確に仮想環境に入っていることがわかります。

(env) yoshi@raspberrypi:~ $ pip list
Package    Version
---------- -------
pip        23.0.1
setuptools 66.1.1

 まっさらな状態ですね。st7789ライブラリをこの仮想環境でpipを使ってインストールします。

(env) yoshi@raspberrypi:~ $ pip install st7789
Looking in indexes: https://pypi.org/simple, https://www.piwheels.org/simple
Collecting st7789
  Using cached https://www.piwheels.org/simple/st7789/ST7789-0.0.4-py3-none-any.whl (8.4 kB)
Installing collected packages: st7789
Successfully installed st7789-0.0.4

(env) yoshi@raspberrypi:~ $ pip list
Package    Version
---------- -------
pip        23.0.1
setuptools 66.1.1
ST7789     0.0.4

 ST7789という名称でインストールされました。以下、ST7798を動かすうえで必要なライブラリを追加でインストールしていきます。

 画像処理のPILライブラリが必要なのでインストールします。

(env) yoshi@raspberrypi:~ $ pip install pillow
Looking in indexes: https://pypi.org/simple, https://www.piwheels.org/simple
Collecting pillow
  Downloading pillow-10.2.0-cp311-cp311-manylinux_2_28_aarch64.whl (4.3 MB)
     ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 4.3/4.3 MB 10.7 MB/s eta 0:00:00
Installing collected packages: pillow
Successfully installed pillow-10.2.0

 数値演算のnumpyが必要なので、インストールします。

(env) yoshi@raspberrypi:~ $ pip install numpy
Looking in indexes: https://pypi.org/simple, https://www.piwheels.org/simple
Collecting numpy
  Downloading numpy-1.26.3-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl (14.2 MB)
     ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 14.2/14.2 MB 11.2 MB/s eta 0:00:00
Installing collected packages: numpy
Successfully installed numpy-1.26.3

 SPIのライブラリspidevが必要なのでインストールします。

(env) yoshi@raspberrypi:~ $ pip install spidev
Looking in indexes: https://pypi.org/simple, https://www.piwheels.org/simple
Collecting spidev
  Downloading spidev-3.6.tar.gz (11 kB)
  Installing build dependencies ... done
  Getting requirements to build wheel ... done
  Installing backend dependencies ... done
  Preparing metadata (pyproject.toml) ... done
Building wheels for collected packages: spidev
  Building wheel for spidev (pyproject.toml) ... done
  Created wheel for spidev: filename=spidev-3.6-cp311-cp311-linux_aarch64.whl size=42573 sha256=5c930da749437f6e120d68406a433c394f5e8b40dff515586fb463a48a3bc5f1
  Stored in directory: /home/yoshi/.cache/pip/wheels/44/f9/7b/01bb1f281eedaaa562943e27c78dee683ee6e7f3bf2f437101
Successfully built spidev
Installing collected packages: spidev
Successfully installed spidev-3.6

 GPIOのアクセスするRPi.GPIOライブラリが必要なのでインストールします。

(env) yoshi@raspberrypi:~ $ pip install RPi.GPIO
Looking in indexes: https://pypi.org/simple, https://www.piwheels.org/simple
Collecting RPi.GPIO
  Downloading RPi.GPIO-0.7.1.tar.gz (29 kB)
  Preparing metadata (setup.py) ... done
Installing collected packages: RPi.GPIO
  DEPRECATION: RPi.GPIO is being installed using the legacy 'setup.py install' method, because it does not have a 'pyproject.toml' and the 'wheel' package is not installed. pip 23.1 will enforce this behaviour change. A possible replacement is to enable the '--use-pep517' option. Discussion can be found at https://github.com/pypa/pip/issues/8559
  Running setup.py install for RPi.GPIO ... done
Successfully installed RPi.GPIO-0.7.1

 インストールしたライブラリを表示します。

(env) yoshi@raspberrypi:~ $ pip list
Package    Version
---------- -------
numpy      1.26.3
pillow     10.2.0
pip        23.0.1
RPi.GPIO   0.7.1
setuptools 66.1.1
spidev     3.6
ST7789     0.0.4

 テスト・プログラムを動かします。

  • portはこのSPI接続ブロックを指します。'0'です。
  • csはChip Selectで、CE0もしくはCE1が利用でき、'0'もしくは'1'を設定します。ここではCE0を接続しています。
  • dcはD/C信号で、GPIO22を接続しています。
  • rstはRSTのリセット信号で、GPIO25を接続しています。

from PIL import Image
from PIL import ImageDraw
from PIL import ImageFont

import ST7789

MESSAGE = "Hello World!"
print(MESSAGE)

#display_type == "dhmini":
disp = ST7789.ST7789(
    height=240,
    width=320,
    rotation=0,
    port=0,
    cs=0,
    dc=22,
    rst=25,
    backlight=None,
    spi_speed_hz=80 * 1000 * 1000,
)


# Initialize display.
disp.begin()

WIDTH = disp.width
HEIGHT = disp.heightimg = Image.new('RGB', (WIDTH, HEIGHT), color=(255, 0, 0))

draw = ImageDraw.Draw(img)

font = ImageFont.truetype("/usr/share/fonts/truetype/dejavu/DejaVuSans-Bold.ttf", 30)

draw.text((20,20),MESSAGE, font=font, fill=(255,255,255))

disp.display(img)

 実行例です。

 envを抜けます。プロンプトが普通の状態になりました。

(env) yoshi@raspberrypi:~ $ deactivate
yoshi@raspberrypi:~ $

 再度この仮想環境に入るには、<有効化>を実行します。

yoshi@raspberrypi:~ $ source env/bin/activate
(env) yoshi@raspberrypi:~ $

--break-system-packagesオプションを利用<その1>

 つぎに、1番目の簡易的な方法を試します。

$ pip list | grep ST7*

 <その2>のenv仮想環境をぬけているので、ST7789ライブラリは表示されません。

$ pip install --break-system-packages st7789
Defaulting to user installation because normal site-packages is not writeable
Looking in indexes: https://pypi.org/simple, https://www.piwheels.org/simple
Collecting st7789
  Downloading https://www.piwheels.org/simple/st7789/ST7789-0.0.4-py3-none-any.whl (8.4 kB)
Installing collected packages: st7789
Successfully installed st7789-0.0.4

 インストールできました。

$ pip list | grep ST7*
ST7789                             0.0.4

$ pip uninstall --break-system-packages st7789
Found existing installation: ST7789 0.0.4
Uninstalling ST7789-0.0.4:
  Would remove:
    /home/yoshi/.local/lib/python3.11/site-packages/ST7789-0.0.4.dist-info/*
    /home/yoshi/.local/lib/python3.11/site-packages/ST7789/*
Proceed (Y/n)? Y
  Successfully uninstalled ST7789-0.0.4


$ pip list | grep ST7*

 消えました。

 確認をします。

$ pip uninstall --break-system-packages st7789

を実行すると、

    /home/yoshi/.local/lib/python3.11/site-packages/ST7789-0.0.4.dist-info/*
    /home/yoshi/.local/lib/python3.11/site-packages/ST7789/*

 .localにインストールされていることがわかります。

 何を確認したかというと、普通のLinuxでは、--userをつけないと、管理者権限で、/userにインストールされるようです。--userをつけてインストールすると、ユーザのホームの中の.localにインストールされるようです。ラズパイのbookworm では、--userをつけなくとも、.localにインストールされていることがわかりました。

 テスト・プログラムを動かします。

 最初に動かした<その2>のプログラムで、インスタンスを作成する、

img = Image.new('RGB', (WIDTH, HEIGHT), color=(0, 0, 0))

 背景のcolorを(255, 0, 0)から(0, 0, 0)に変更しました。

 実行すると、最初に画面がいっしゅん白くなり、文字を表示したとき、背景は黒色になりました。

 この.local環境では、numpy、pillow、RPi.GPIO、spidev などは、最初から入っているので、インストールは不要です。

 インストールしたST7789ライブラリを削除します。

 $ pip uninstall --break-system-packages st7789
Found existing installation: ST7789 0.0.4
Uninstalling ST7789-0.0.4:
  Would remove:
    /home/yoshi/.local/lib/python3.11/site-packages/ST7789-0.0.4.dist-info/*
    /home/yoshi/.local/lib/python3.11/site-packages/ST7789/*
Proceed (Y/n)? Y
  Successfully uninstalled ST7789-0.0.4
$ pip list | grep ST7*

$

 削除されました。

pipxを利用<その3>

$ sudo apt-get install pipx
Reading package lists... Done
Building dependency tree... Done
Reading state information... Done
The following additional packages will be installed:

。。。以下、多くのパッケージがインストールされる。

$ pipx install st7789

No apps associated with package st7789 or its dependencies. If you are attempting to install a library, pipx should
not be used. Consider using pip or a similar tool instead.

 どうも使えないようですね。

気圧を表示

 すごく手間がかかりましたが、前回I2Cバスに接続した気圧センサLPS22HBの測定値を、このTFTディスプレイに表示します。

 ディスプレイのライブラリのインストールは一番簡便な<その1>を利用します。

$ pip install --break-system-packages st7789

 プログラムです。

import smbus2
import time
from PIL import Image
from PIL import ImageDraw
from PIL import ImageFont

import ST7789

i2c =  smbus2.SMBus(1)
addr = 0x5d

i2c.write_byte_data(addr, 0x10, 0x10)

disp = ST7789.ST7789(height=240,width=320,rotation=0,
    port=0,cs=0,dc=22,rst=25,backlight=None,
    spi_speed_hz=80 * 1000 * 1000
)

disp.begin()
img = Image.new('RGB', (disp.width, disp.height), color=(32, 32, 32))
draw = ImageDraw.Draw(img)
font = ImageFont.truetype("/usr/share/fonts/truetype/noto/NotoMono-Regular.ttf", 40)
draw.text((10,0),'Temp & press', font=font, fill=(255,0,0))
disp.display(img)
time.sleep(2)

while 1:
    i2c.write_byte_data(addr, 0x11, 0x11)
    pdata_XL = i2c.read_byte_data(addr, 0x28)
    pdata_L  = i2c.read_byte_data(addr, 0x29)
    pdata_H  = i2c.read_byte_data(addr, 0x2a)
    press = (pdata_H<<16 | pdata_L << 8 | pdata_XL ) / 4096.0
    Press = str(int(press))
    print("\nPress = " + Press + "hPa")
    tdata_L = i2c.read_byte_data(addr, 0x2b)
    tdata_H = i2c.read_byte_data(addr, 0x2c)
    temp = (tdata_H << 8 | tdata_L ) / 100.0
    Temp = str(round(temp,1))
    print("Temp  = " + Temp + "`C")

    draw.rectangle((20, 50, 200,160), (32,32,32))
    draw.text((20,50),Temp+'`C', font=font, fill=(25,255,25))
    draw.text((20,100),Press+'hPa', font=font, fill=(25,255,25))
    disp.display(img)
    time.sleep(2)

 実行結果です。

-