🎎
【Wio Terminal/LvGL】スイッチ操作でスライダーを動かす
タッチスクリーンでなくとも画面操作できる
以前、Seeed_Arduino_LvGL
の基本的な使い方を調べるも様々な情報に踊らされ、瞋恚の末竟に癲狂したのだが、それはさて置き使えるようにはなったのだった。
しかし
プログラム
主としてこの例を参考に、プログラムを作成した。
引用:https://www.switch-science.com/products/6360
そしてこれらを入力として扱うことができる。プログラムの概要はコメントを見よ。
value-slider.ino
#include <lvgl.h>
#include <TFT_eSPI.h>
/* tick period */
constexpr uint16_t TICK_PERIOD = 5;
/* TFT LCD */
static TFT_eSPI TFT;
/* display buffer */
static lv_disp_buf_t DISP_BUF;
/* color buffer */
static lv_color_t COLOR_BUF[LV_HOR_RES_MAX * 10];
/* input device */
static lv_indev_t* INPUT_DEVICE;
/* input deviceの影響を被るグループ */
static lv_group_t* INPUT_GROUP;
/* slider */
static lv_obj_t* SLIDER;
/* input deviceの値を示すラベル */
static lv_obj_t* LABEL_SLIDERS_VALUE;
/* 画面初期化 */
void display_flush(
lv_disp_drv_t* disp,
const lv_area_t* area,
lv_color_t* color_p
);
/* Reading input device (嘘) */
bool read_encoder(
lv_indev_drv_t* indev,
lv_indev_data_t* data
);
/* system tick */
static void tick_handler();
/* 設定 */
void backend_setup();
/* slider event callback */
static void slider_event_cb(
lv_obj_t* SLIDER,
lv_event_t event
);
/* 画面要素 */
void set_contents();
/* 5way switch */
void wio_joy_handler();
void set_contents() {
/* sliderの設定 */
SLIDER = lv_slider_create(lv_scr_act(), NULL);
/* 幅 */
lv_obj_set_width(SLIDER, LV_DPI * 2);
/* 画面中央に配置する */
lv_obj_align(SLIDER, NULL, LV_ALIGN_CENTER, 0, 0);
/* callbackを設定する */
lv_obj_set_event_cb(SLIDER, slider_event_cb);
/* 値の取る範囲 */
lv_slider_set_range(SLIDER, 0, 100);
/* アニメーションの時間 */
lv_slider_set_anim_time(SLIDER, 75);
/* slider値を示すlabelの設定 */
LABEL_SLIDERS_VALUE = lv_label_create(lv_scr_act(), NULL);
/* 初期表示 */
lv_label_set_text(LABEL_SLIDERS_VALUE, "0");
/* 自動整理 */
lv_obj_set_auto_realign(LABEL_SLIDERS_VALUE, true);
/* sliderを基準とし、下部中央に配置する */
lv_obj_align(LABEL_SLIDERS_VALUE, SLIDER, LV_ALIGN_OUT_BOTTOM_MID, 0, 10);
/* 説明labelの設定 */
/* 1行目 */
lv_obj_t* info1 = lv_label_create(lv_scr_act(), NULL);
lv_label_set_text(
info1,
"This is the joy switch + SLIDER demo."
);
lv_obj_align(info1, NULL, LV_ALIGN_IN_TOP_MID, 0, 10);
/* 2行目 */
lv_obj_t* info2 = lv_label_create(lv_scr_act(), NULL);
/* スクロール */
lv_label_set_long_mode(info2, LV_LABEL_LONG_SROLL_CIRC);
/* 幅 */
lv_obj_set_width(info2, LV_HOR_RES_MAX);
/* スクロール設定後に文章を定める */
lv_label_set_text(
info2,
"Move the switch right/up, SLIDER moves to right."
);
lv_obj_align(info2, info1, LV_ALIGN_OUT_BOTTOM_MID, 0, 0);
/* 3行目 */
lv_obj_t* info3 = lv_label_create(lv_scr_act(), NULL);
lv_label_set_long_mode(info3, LV_LABEL_LONG_SROLL_CIRC);
lv_obj_set_width(info3, LV_HOR_RES_MAX);
lv_label_set_text(
info3,
"Move the switch left/down, SLIDER moves to left."
);
lv_obj_align(info3, info2, LV_ALIGN_OUT_BOTTOM_MID, 0, 0);
/* 4行目 */
lv_obj_t* info4 = lv_label_create(lv_scr_act(), NULL);
lv_label_set_long_mode(info4, LV_LABEL_LONG_SROLL_CIRC);
lv_obj_set_width(info4, LV_HOR_RES_MAX);
lv_label_set_text(
info4,
"Press the switch, SLIDER moves to the left end."
);
lv_obj_align(info4, info3, LV_ALIGN_OUT_BOTTOM_MID, 0, 0);
/* groupの設定 */
INPUT_GROUP = lv_group_create();
/* input deviceを設定する */
lv_indev_set_group(INPUT_DEVICE, INPUT_GROUP);
/* sliderを追加する */
lv_group_add_obj(INPUT_GROUP, SLIDER);
}
void wio_joy_handler() {
/*
↑: LV_KEY_UP
↓: LV_KEY_DOWN
←: LV_KEY_LEFT
→: LV_KEY_RIGHT
UP or RIGHT: increment
DOWN or LEFT: decrement
PRESS: 0
*/
if (digitalRead(WIO_5S_UP) == LOW) {
/* groupに入力LV_KEY_UPを送る */
lv_group_send_data(INPUT_GROUP, LV_KEY_UP);
}
else if (digitalRead(WIO_5S_DOWN) == LOW) {
/* groupに入力LV_KEY_DOWNを送る */
lv_group_send_data(INPUT_GROUP, LV_KEY_DOWN);
}
else if (digitalRead(WIO_5S_LEFT) == LOW) {
/* groupに入力LV_KEY_LEFTを送る */
lv_group_send_data(INPUT_GROUP, LV_KEY_LEFT);
}
else if (digitalRead(WIO_5S_RIGHT) == LOW) {
/* groupに入力LV_KEY_RIGHTを送る */
lv_group_send_data(INPUT_GROUP, LV_KEY_RIGHT);
}
else if (digitalRead(WIO_5S_PRESS) == LOW) {
/* sliderの値を0にする */
lv_slider_set_value(SLIDER, 0, LV_ANIM_ON);
}
else {
/* 何もない時は何もしない */
return;
}
/* イベントは勝手に起こらないため、ここで起こす */
lv_event_send(SLIDER, LV_EVENT_VALUE_CHANGED, NULL);
}
void setup() {
/* 設定 */
backend_setup();
/* 画面構成 */
set_contents();
}
void loop() {
tick_handler();
lv_task_handler();
wio_joy_handler();
delay(TICK_PERIOD);
}
value-slider-settings.ino
/*
画面初期化
画面いっぱい色で塗り潰している
*/
void display_flush(
lv_disp_drv_t* disp,
const lv_area_t* area,
lv_color_t* color_p
) {
uint32_t w = (area->x2 - area->x1 + 1);
uint32_t h = (area->y2 - area->y1 + 1);
TFT.startWrite();
TFT.setAddrWindow(area->x1, area->y1, w, h);
TFT.pushColors(&color_p->full, w * h, true);
TFT.endWrite();
/* callbackではこれを召喚しなければならない */
lv_disp_flush_ready(disp);
}
/* Reading input device (嘘) */
bool read_encoder(
lv_indev_drv_t* indev,
lv_indev_data_t* data
) {
/* no input */
return false;
}
/* system tick */
void tick_handler() {
lv_tick_inc(TICK_PERIOD);
}
/* slider event callback */
static void slider_event_cb(lv_obj_t* SLIDER, lv_event_t event) {
if (event == LV_EVENT_VALUE_CHANGED) {
static char buf[4]; /* max 3 bytes for number plus 1 null terminating byte */
snprintf(buf, 4, "%u", lv_slider_get_value(SLIDER));
lv_label_set_text(LABEL_SLIDERS_VALUE, buf);
}
}
/* 設定 */
void backend_setup() {
/* lvglの初期化 */
lv_init();
/* TFTの初期設定 */
TFT.begin();
TFT.setRotation(3);
/* 画面表示用bufferそのものの初期化 */
lv_disp_buf_init(&DISP_BUF, COLOR_BUF, NULL, LV_HOR_RES_MAX * 10);
/* 画面制御設定 */
lv_disp_drv_t disp_drv;
lv_disp_drv_init(&disp_drv);
disp_drv.hor_res = LV_HOR_RES_MAX;
disp_drv.ver_res = LV_VER_RES_MAX;
disp_drv.flush_cb = display_flush;
disp_drv.buffer = &DISP_BUF;
lv_disp_t* pDisplay = lv_disp_drv_register(&disp_drv);
/* 入力の設定 */
lv_indev_drv_t indev_drv;
lv_indev_drv_init(&indev_drv);
indev_drv.type = LV_INDEV_TYPE_ENCODER;
indev_drv.read_cb = read_encoder;
INPUT_DEVICE = lv_indev_drv_register(&indev_drv);
/* enable 5way switch */
pinMode(WIO_5S_UP, INPUT);
pinMode(WIO_5S_DOWN, INPUT);
pinMode(WIO_5S_LEFT, INPUT);
pinMode(WIO_5S_RIGHT, INPUT);
pinMode(WIO_5S_PRESS, INPUT);
}
LV_KEY_*
によるスライダーの増減は我々が決める必要のあることではなく、次のように定義されている。
つまり、スイッチによる物理的な入力を、LV_KEY_*
などと謂う仮想的な入力へ対応付けるだけで宜い。
なお、説明文は長すぎて画面に収まらないため、自動スクロールするようになっている。
実行結果
次の様子が見て取れる。
- 画面上半分の文章が流動している
- スライダーが移動している
- スライダー下部のラベル表示が変化している
スイッチ操作前
スイッチ操作後
Discussion