最短翌日発送!高速大容量のモバイルWi-Fiルーターの詳細はこちら
DIY・電子工作

【OpenAuto Pro】Waveshare製タッチパネルの画面輝度をソフトウェアで制御する方法

Waveshare製タッチパネルをPWMでバックライトを制御する様子 DIY・電子工作

※この記事には広告(アフィリエイトリンク)が含まれますのであらかじめご了承ください。

OpenAuto ProでAndroid Auto搭載カーナビを自作するにあたって鬼門なのがディスプレイ、タッチパネルの選定です。

Raspberry Pi公式の7インチタッチパネルが扱いやすくて無難ではありますが、7インチのわりには解像度が800×480と低く、今時とは思えないベゼルの太さに1万円強という価格は躊躇ってしまいます。。

そこでサードパーティーに目を向けてみると、Waveshareというメーカーが多種多様なタッチパネルを販売していてこれを使いたくなるのですが…HDMI接続の8DP-CAPLCDを購入したところ、公式タッチパネルと同じようにはバックライトの明るさを調節できないという罠がありました。商品ページではタッチ操作で調整できるかのように紹介されているんですけどねえ…

バックライトの明るさを調節できないと、輝度最大の状態で暗い夜道を走行するのは危険ですし、逆に輝度を抑えると日が明るい時間帯の視認性が悪くなってしまいます。夜間モードに切り替えれば黒を基調としたUIに変更されるので少しはマシになりますが、可能ならバックライトの輝度も落としたいところです。

そこで他の手段はないかとWaveshareに問い合わせたところ、最終的にRaspberry PiのハードウェアPWMを利用して制御する方法を教えてもらえました。

厳密には教えてもらった方法そのままでは上手くいかなかったのですが、しっかり輝度を制御できる方法を確立できたのでその方法をまとめておきます。同じ基板を使用しているものなら他のタッチパネルでも同じ方法で制御可能と思われますし、そうでなくても同じアプローチでどうにかなるかもしれません。

ただし基板を改造するため最悪破損、故障させる恐れがあります。真似する場合は慎重に、かつ自己責任でお願いします。。

スポンサーリンク
スポンサーリンク

OpenAuto Proに日中モードと夜間モードの切り替え機能はあるが…

Android AutoではGoogleマップやYahoo!マップで地図を表示させることが可能です。そしてこれらのアプリは日中モードと夜間モードを切り替えることで、時間帯や環境に合わせて視認性が良いUIに変更されます。

OpenAuto Proにはこの日中モードと夜間モードを切り替えるための機能が用意されており、以下のいずれかの方法で切り替えることが可能です。

  • ライトセンサー(周囲の明るさに応じて切り替え)
  • 時間帯
  • GPIO(ヘッドライトなどイルミ電源と連動して切り替え)
  • GUI(手動で切り替え)

バックライトの輝度は他の方法で制御する必要がある

ただし日中モードと夜間モードを切り替えて変更されるのはあくまでもUIであって、バックライトの輝度を制御することはできません。

バックライトの明るさを変更するためには、他の方法を考えなくてはいけません。

8DP-CAPLCDのバックライトの明るさを調節する3つの方法

今回私が使用した8DP-CAPLCDでバックライトの明るさを調節する方法は大きく分けて3つありました。

物理ボタンでOSDを操作する

まずは一般的なPCモニターと同じように物理ボタンを使用してOSDを操作する方法です。

製品に同梱されている物理ボタンを基板に接続することで、OSDを操作してバックライトの明るさを調節することが可能でした。

しかしこの方法だとライトセンサーやGPIOを利用して輝度を自動調整することはできません。また操作手順が多いので、到底運転中に使用するような手段ではないでしょう。

コマンドラインで操作する

Waveshareに問い合わせて最初に得られた回答がこれでした。

Raspberry Piがグラフィックスドライバーとしてkmsドライバーを使用している場合、以下のようにddcutilを使用することでコマンドラインからバックライトの明るさを変更することが可能です。

$ sudo apt install ddcutil
$ ddcutil capabilities | grep Brightness
$ ddcutil getvcp 10 #現在の輝度の値を取得
$ ddcutil setvcp 10 30 #輝度の値を30に変更

ところがこのkmsドライバーが問題で、現在はfkmsドライバーが主流になっています。Raspberry Pi OS自体はkmsドライバーでも動作しますが、Android Autoを実行するためにはfkmsドライバーのロードが必須です。そのためkmsドライバーをロードしている状態でAndroid Autoを実行しようとしても画面がブラックアウトして正常に表示されません。

グラフィックスドライバーを切り替えるためにはOSの再起動が必要で、OSD以上に非現実的な手段です。

ちなみにグラフィックスドライバーの指定は/boot/config.txtに以下のように記述します。fkmsの部分がkmsだとkmsドライバーをロードするので注意してください。

dtoverlay=vc4-fkms-v3d

基板を改造してハードウェアPWM、ソフトウェアで制御する

基板の抵抗を取り除いてPWMと接続した様子

自力で調べてみてもfkmsドライバーで有効な方法がOSD以外に見つからなかったので、Waveshareに何でも良いから他に方法がないかと食い下がったところ、PWMで制御する方法を調べて教えていただきました。

具体的には画像の赤枠部分にある抵抗を取り除いて、紫色で囲った下側のパッドにPWMを接続します。Raspberry Pi 4Bの場合はGPIO18、またはGPIO19でハードウェアPWMを使用することが可能なので、これと接続すればOKです。

抵抗は小さくてかなり細かい作業ですが、抵抗を覆い尽くすくらいのはんだを盛ってやって、はんだごてで突いたら簡単に跳ね上がって取れました。

ちなみにRaspberry Pi側でPWMを未設定のまま起動させるとディスプレイが真っ暗で何も表示されませんが、焦らなくても大丈夫です。

wiringpiでPWMを制御するPythonプログラムを作成する

Raspberry PiでハードウェアPWMを制御する方法はいくつかありますが、Waveshareが教えてくれた方法では何も起きずダメでした。

また方法によっては輝度の調節ができても、明るさが最大でなければディスプレイがチラついてしまう問題が発生しました。

いろいろ試してみた結果、wiringpiライブラリを使用することで無事ソフトウェアでハードウェアPWMを制御することが可能になりました。最新のRaspberry Pi OSではRPi.GPIOを使用するのが推奨されているようですが、とりあえずwiringpiで上手くいったのでこれを実装してみます。なお明示的にPython3で実行しないと上手くいきませんでした。

まずはwiringpiをインストールするために以下のコマンドを実行します。

$ sudo apt install wiringpi
$ sudo pip3 install wiringpi

次にPythonプログラムを作成して、手動で調節できるか確認してみましょう。

$ sudo nano test.py
#!/usr/bin/env python3

import wiringpi

wiringpi.wiringPiSetupGpio()

PIN = 18
PWM_RANGE = 100
PWM_CLOCK = 1920
wiringpi.pinMode(PIN, wiringpi.GPIO.PWM_OUTPUT)
wiringpi.pwmSetRange(PWM_RANGE)
wiringpi.pwmSetClock(PWM_CLOCK)

while True:
    duty = int(input("Enter duty cycle (0-100): "))
    wiringpi.pwmWrite(PIN, int(PWM_RANGE * duty / 100))
$ sudo python3 test.py

このプログラムではPWMの出力にGPIO18を使用します。PWM信号の範囲は100、周波数は1920に設定しました。

実行してduty、デューティサイクルの値を入力すると、値に応じてバックライトの輝度も変化するはずです。100だともっとも明るくなり、0だと完全に何も映りません。

動作確認が取れたら、ヘッドライト点灯時のみ輝度を抑えるようなプログラムを作成します。

イルミ電源とバックライトを連動させるPythonプログラムを作成する

#!/usr/bin/env python3

import wiringpi

wiringpi.wiringPiSetupGpio()

PWM_PIN = 18
PWM_RANGE = 100
PWM_CLOCK = 1920
wiringpi.pinMode(PWM_PIN, wiringpi.GPIO.PWM_OUTPUT)
wiringpi.pwmSetRange(PWM_RANGE)
wiringpi.pwmSetClock(PWM_CLOCK)

MONITOR_PIN =16

prev_input = wiringpi.digitalRead(MONITOR_PIN)

duty = 100

while True:
    input = wiringpi.digitalRead(MONITOR_PIN)
    if input != prev_input:
        if input == 1:
            duty = 100
        else:
            duty = 20
        prev_input = input
    wiringpi.pwmWrite(PWM_PIN, int(PWM_RANGE * duty / 100))

ヘッドライトの点灯はイルミ電源にリレーを繋ぐことで検出可能です。筆者は5極リレーを使用して、リレー非作動時にGPIO16が通電するように取り付けました。リレー作動時に通電するGPIOは夜間モードの切り替えに使用するためです。

dutyの初期値として100を設定しておいて、GPIO16が通電してる場合はduty=100、通電しなくなった場合はduty=20に変更するようにしました。

これも期待通りに動作することを確認できたら、仕上げとしてSystemdに登録してサービスとして自動起動するようにしておきましょう。

$ sudo nano /etc/systemd/system/backlight.service
[Unit]
Description = Backlight Control

[Service]
ExecStart = /usr/bin/python3 /opt/backlight.py
Restart = always
Type = simple

[Install]
WantedBy = multi-user.target
$ sudo chmod 0755 /opt/backlight.py
$ sudo systemctl enable backlight
$ sudo systemctl start backlight

Raspberry Piを再起動してもディスプレイがブラックアウトせず正常に表示されていればOKです。

まとめ

WaveshareはRaspberry Pi向けに様々なタッチパネル搭載ディスプレイを販売していて魅力的ですが、中にはバックライトの輝度をソフトウェアで調節することが難しいモデルもあるようなので注意が必要です。

筆者が購入した8DP-CAPLCDと同じ基板を使用しているモデルなら、同じように抵抗を取り除けばPWMで制御することが可能かと思われます。基板が異なるモデルでも、メーカーに問い合わせればその基板に適した方法を検証して教えてくれるかもしれません。

PWMで制御できればヘッドライトに連動して明るさを抑えることも可能です。基板を改造することになるのであまり推奨すべきではないかもしれませんが、そもそもOpenAuto Proに手を出すような人ならそんなことは気にしないですよね(ぇ

とはいえ実行する場合はあくまでも自己責任でお願いします。。

コメント

タイトルとURLをコピーしました