MicroPythonを入れたESP32でモノクロ反射型TFTメモリ液晶LS027B4DH01用のGUIを作ってみる

2020/09/19 categories:ESP32| tags:ESP32|MicroPython|LS027B4DH01|GUI|

マイコンと液晶を使う場合に液晶に表示する内容を考える必要があります。基本的には文字を表示したり、ボタンを表示したりすることが必要になります。今回はこれらの文字表示とボタンの表示を行い、スイッチからの入力でボタンを選択して状態遷移をするプログラムを作成してみました。

動作の様子

メインのプログラム

メインのプログラムは作成したGUI_testというクラスのrunを無限ループで実行し続けるというプログラムにしました。GUI_testのrun内では、状態(state)に応じて制御(control)と描画(draw)を行うという処理にしています。これで現在の状態に応じて処理や表示を返ることができました。

class GUI_test():
    def __init__(self):
        self.states = {
            'home'         : Ui_home(self), 
            'acceleration' : Ui_acceleration(self), 
            'gyro'         : Ui_gyro(self), 
            'geomagnetism' : Ui_geomagnetism(self)
        }
        self.state = 'home'

    def run(self):
        obj = self.states[self.state]
        obj.control( self.button.read() )
        obj.draw()

    def change_state(self, state):
        self.state = state

def main():
    gui_test = GUI_test()
    while True:
        gui_test.run()

UIクラス

UIというクラスを作成してGUIに必要なオブジェクトを用意しました。今回はとりあえずボタンとテキスト表示だけ出来ればよかったので、buttonsとtextsを表示するプログラムにしています。それらをappend_buttonとappend_textで追加して、それら全てをdrawでLCDに描画します。

class UI(object):
    def __init__(self, lcd):
        self.lcd, self.buttons, self.texts = lcd, {}, {}

    def append_button(self, name, x, y, text):
        self.buttons[name] = Button(self, x, y, text)

    def append_text(self, name, x, y, text):
        self.texts[name] = Text(self, x, y, text)

    def draw(self):
        self.lcd.data_reset()

        for text in self.texts:
            self.texts[text].draw()
        
        for button in self.buttons:
            self.buttons[button].draw()
        
        self.lcd.data_update_all_line()

加速度表示クラス

上記のUIクラスを継承して、ホーム画面、加速度、角加速度、地磁気を表示するクラスを作成しました。初期化でtextやbuttonを追加して、buttonには選択したときに実行する関数をセットします。

class Ui_acceleration(UI):
    def __init__(self, parent):
        super(Ui_acceleration, self).__init__(parent.lcd)
        self.parent = parent
        self.append_text('text_4',  50,  60, '0.000')
        self.append_button('button_0', 200, 200, 'back')
        self.buttons['button_0'].set_action( lambda : self.parent.change_state('home') )

このクラスで行う処理はcontrol関数に書いています。ここでは入力に対して表示を変更するという処理を行っており、キー入力があればボタンの処理を行い、センサの入力をテキストに反映させるという処理をしています。

    def control(self, button):
        if button['right']:
            self.buttons['button_0'].action()
            return
        accel = self.parent.mpu9250.read_accel()
        self.texts['text_4'].set_text( str(accel['x']) )

UIクラスのdrawメソッドとそれを継承したクラスのcontrolメソッドをメインプログラムのrunメソッド内で呼び出すようにして、状態に応じた制御と描画が出来るようにしました。

def run(self):
    obj = self.states[self.state]
    obj.control( self.button.read() )
    obj.draw()

キー入力

キー入力はジョイスティックで行いました。ジョイスティックの可変抵抗をAD変換して、変換結果が閾値を超えた場合にその方向にキー入力したと判定しています。それを行うJoystickクラスは辞書として扱えるように__getitem__や__setitem__メソッドを用意しています。

class Joystick():
    def __init__(self, x, y, s=None):

    def __getitem__(self, key):
        return self.__dict__[key]

    def __setitem__(self, key, value):
        self.__dict__[key] = value

    def read(self):
        self.x_data[0] = self.x_data[1]
        self.y_data[0] = self.y_data[1]
        self.x_data[1] = self.x_pin.read() - self.center
        self.y_data[1] = self.y_pin.read() - self.center
        self.__dict__['up']     = self.up()
        return self

    def up(self):
        return ( self.x_data[1] > self.threshold ) \
            and ( self.x_data[0] < self.threshold )

ホーム画面では、このJoystickクラスを利用してジョイスティックを上下に傾けたときに選択されているボタンを変更して、右に傾けたときにボタンの決定を行うという処理をしています。

def control(self, button):
    if button['up']:
        self.set_select_button(-1)

    if button['down']:
        self.set_select_button(1)

    if button['right']:
        self.selected_button().action()

ソースコード

githubにアップロードしました

Share post

Related Posts

コメント