はじめに
この記事は、EV3にev3devをインストールし、SSH接続できている状態であることを前提にしています。環境構築ができていない方はこちらの記事を参考にしてください。
mindstorm-EV3をLinuxで制御しよう! ev3dev OSのインストールとSSH接続
概要
ev3devではEV3のLCDをどのように制御できるのか、サンプルコードを図を用いて解説します。
python製ライブラリのev3dev-lang-pythonにはLCDを簡単に制御できるAPIが提供されていますが、今回はそれらのライブラリを使わずにLCD制御の仕組みを理解することが目的です
LCDの仕組み
EV3のLCDは178 x 128ピクセルのモノクロ画面になっています。
ビデオドライバーはLinuxのframebufferインターフェースによって提供されていて、デバイスファイル/dev/fb0にデータを書き込むことでLCDを制御できます。
framebufferの情報をfbset -i
コマンドを実行して確かめてみましょう。
robot@ev3dev:~$ fbset -i
mode "178x128"
geometry 178 128 178 128 1
timings 0 0 0 0 0 0 0
rgba 1/0,1/0,1/0,0/0
endmode
Frame buffer device information:
Name : ST7586
Address : 0xc39f9000
Size : 3072
Type : PACKED PIXELS
Visual : MONO01
XPanStep : 0
YPanStep : 0
YWrapStep : 0
LineLength : 24
Accelerator : No
LCDが178 x 128ピクセルで構成されること、水平方向一列のピクセル情報が24byteで表させることが分かります。
(下図)
LCDはモノクロ(カラーではない)なので、それぞれの最小ピクセルは0か1のバイナリーデータとなります。
1byte=8bitなので、178pxを表現するには178/8=22.25(byte)あれば足ります。しかし実際には、水平方向一列のピクセル情報は24byteで表現されます。つまり24byteのデータ全てが画面上に表示されるわけではないということです。
サンプルコード
LCDを制御するには24byte x 128(rows) = 3072byteのデータをデバイスファイルに書き込む必要があります。
以下の図形を表示させるサンプルコードは以下のようになります。
# !/usr/bin/env python
# Hard coding these values is not a good idea because the values could
# change. But, since this is an example, we want to keep it short.
SCREEN_WIDTH = 178 # pixels
SCREEN_HEIGHT = 128 # pixels
LINE_LENGTH = 24 # bytes
SIZE = 3072 # bytes
import os
import array
def main():
# 要素数3072の配列を定義
buf = [0] * SIZE
# 100カラム目に縦線を引く
for row in range(0, SCREEN_HEIGHT):
buf[row * LINE_LENGTH + int(100 / 8)] = 1 << (100 % 8)
# 64列目に水平線を引く
for col in range(0, LINE_LENGTH):
buf[64 * LINE_LENGTH + col] = 0xff
import math
# 中心点 (40,40), 半径 20の円を描く
for x in range(0, 20):
y = math.sqrt(20 * 20 - x * x)
buf[(40 + int(y)) * LINE_LENGTH + int((40 + x) / 8)] = 1 << ((40 + x) % 8)
buf[(40 - int(y)) * LINE_LENGTH + int((40 + x) / 8)] = 1 << ((40 + x) % 8)
buf[(40 + int(y)) * LINE_LENGTH + int((40 - x) / 8)] = 1 << ((40 - x) % 8)
buf[(40 - int(y)) * LINE_LENGTH + int((40 - x) / 8)] = 1 << ((40 - x) % 8)
# デバイスファイルへの書き込み
f = os.open('/dev/fb0', os.O_RDWR)
s = array.array('B', buf).tostring()
os.write(f, s)
os.close(f)
if __name__ == '__main__':
main()
コードを保存させ実行するとLCD画面に図形が表示されます。
ライブラリに定義されていないような複雑なLCD制御をしたい場合、参考になると思います。