Files
humanInfraredModuletest/src/ui.cpp
DESKTOP-PUHFO60\dsx2016 bab93d0e36 Add human IR (PIR) module test on GPIO22 with SoftSPI touch and LVGL.
Motion-start count, hold bar, auto polarity, and flashable firmware/cyd package.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-10-23 14:46:56 +08:00

155 lines
5.4 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#include "ui.h"
#include "pir.h"
#include "pins.h"
#include <Arduino.h>
#include <lvgl.h>
#include <stdio.h>
static constexpr uint32_t COL_BG = 0x0A1016;
static constexpr uint32_t COL_INK = 0xEAF0F6;
static constexpr uint32_t COL_MUTED = 0x7A8B9C;
static constexpr uint32_t COL_BTN = 0x243140;
static constexpr uint32_t COL_ACCENT = 0x4FC3F7;
static constexpr uint32_t COL_HOT = 0xFF7043;
static lv_obj_t *lbl_title;
static lv_obj_t *lbl_pin;
static lv_obj_t *lbl_count;
static lv_obj_t *lbl_hint;
static lv_obj_t *lbl_state;
static lv_obj_t *lbl_hold;
static lv_obj_t *lbl_raw;
static lv_obj_t *bar_hold;
static lv_obj_t *btn_reset;
static lv_obj_t *lbl_reset;
static void style_btn(lv_obj_t *btn, uint32_t bg) {
lv_obj_set_style_radius(btn, 10, 0);
lv_obj_set_style_bg_color(btn, lv_color_hex(bg), 0);
lv_obj_set_style_bg_opa(btn, LV_OPA_COVER, 0);
lv_obj_set_style_shadow_width(btn, 0, 0);
lv_obj_set_style_border_width(btn, 0, 0);
lv_obj_set_style_pad_all(btn, 0, 0);
}
void ui_refresh() {
if (lbl_count) {
lv_label_set_text_fmt(lbl_count, "%lu", (unsigned long)pir_count());
}
const bool active = pir_is_active();
const uint32_t hold = pir_hold_ms();
if (lbl_state) {
lv_label_set_text(lbl_state, active ? "MOTION" : "IDLE");
lv_obj_set_style_text_color(lbl_state,
lv_color_hex(active ? COL_HOT : COL_MUTED), 0);
}
if (lbl_hold) {
if (active) {
lv_label_set_text_fmt(lbl_hold, "hold %lu ms", (unsigned long)hold);
} else {
lv_label_set_text(lbl_hold, "hold --");
}
}
if (bar_hold) {
// 条:0~5s 映射到 0~100,便于看保持时间
uint32_t pct = hold / 50;
if (pct > 100) {
pct = 100;
}
lv_bar_set_value(bar_hold, (int32_t)pct, LV_ANIM_OFF);
lv_obj_set_style_bg_color(bar_hold,
lv_color_hex(active ? COL_HOT : 0x1A2430),
LV_PART_INDICATOR);
}
if (lbl_raw) {
const int lv = pir_raw_level();
lv_label_set_text_fmt(lbl_raw, "OUT %s act=%s", lv ? "HIGH" : "LOW",
pir_active_level() ? "HIGH" : "LOW");
lv_obj_set_style_text_color(lbl_raw,
lv_color_hex(lv ? 0x3DDC97 : COL_MUTED), 0);
}
}
static void on_reset(lv_event_t *e) {
if (lv_event_get_code(e) != LV_EVENT_CLICKED) {
return;
}
pir_reset_count();
ui_refresh();
}
void ui_create() {
lv_obj_t *scr = lv_screen_active();
lv_obj_set_style_bg_color(scr, lv_color_hex(COL_BG), 0);
lv_obj_set_style_bg_opa(scr, LV_OPA_COVER, 0);
lbl_title = lv_label_create(scr);
lv_label_set_text(lbl_title, "Human IR");
lv_obj_set_style_text_color(lbl_title, lv_color_hex(COL_INK), 0);
lv_obj_set_style_text_font(lbl_title, &lv_font_montserrat_28, 0);
lv_obj_align(lbl_title, LV_ALIGN_TOP_MID, 0, 2);
lbl_pin = lv_label_create(scr);
lv_label_set_text_fmt(lbl_pin, "OUT->GPIO%d VCC 3.3V", PIR_PIN);
lv_obj_set_style_text_color(lbl_pin, lv_color_hex(COL_MUTED), 0);
lv_obj_set_style_text_font(lbl_pin, &lv_font_montserrat_14, 0);
lv_obj_align(lbl_pin, LV_ALIGN_TOP_MID, 0, 32);
lbl_count = lv_label_create(scr);
lv_label_set_text(lbl_count, "0");
lv_obj_set_style_text_color(lbl_count, lv_color_hex(COL_ACCENT), 0);
lv_obj_set_style_text_font(lbl_count, &lv_font_montserrat_28, 0);
lv_obj_align(lbl_count, LV_ALIGN_TOP_MID, 0, 54);
lbl_hint = lv_label_create(scr);
lv_label_set_text(lbl_hint, "detects");
lv_obj_set_style_text_color(lbl_hint, lv_color_hex(COL_MUTED), 0);
lv_obj_set_style_text_font(lbl_hint, &lv_font_montserrat_14, 0);
lv_obj_align(lbl_hint, LV_ALIGN_TOP_MID, 0, 88);
lbl_state = lv_label_create(scr);
lv_label_set_text(lbl_state, "IDLE");
lv_obj_set_style_text_color(lbl_state, lv_color_hex(COL_MUTED), 0);
lv_obj_set_style_text_font(lbl_state, &lv_font_montserrat_20, 0);
lv_obj_align(lbl_state, LV_ALIGN_TOP_MID, 0, 108);
lbl_hold = lv_label_create(scr);
lv_label_set_text(lbl_hold, "hold --");
lv_obj_set_style_text_color(lbl_hold, lv_color_hex(COL_MUTED), 0);
lv_obj_set_style_text_font(lbl_hold, &lv_font_montserrat_14, 0);
lv_obj_align(lbl_hold, LV_ALIGN_TOP_MID, 0, 132);
bar_hold = lv_bar_create(scr);
lv_obj_set_size(bar_hold, UI_HOR_RES - 48, 10);
lv_obj_align(bar_hold, LV_ALIGN_TOP_MID, 0, 152);
lv_bar_set_range(bar_hold, 0, 100);
lv_bar_set_value(bar_hold, 0, LV_ANIM_OFF);
lv_obj_set_style_bg_color(bar_hold, lv_color_hex(0x1A2430), LV_PART_MAIN);
lv_obj_set_style_bg_opa(bar_hold, LV_OPA_COVER, LV_PART_MAIN);
lv_obj_set_style_radius(bar_hold, 4, LV_PART_MAIN);
lv_obj_set_style_bg_color(bar_hold, lv_color_hex(COL_HOT), LV_PART_INDICATOR);
lv_obj_set_style_radius(bar_hold, 4, LV_PART_INDICATOR);
lbl_raw = lv_label_create(scr);
lv_label_set_text(lbl_raw, "OUT --");
lv_obj_set_style_text_color(lbl_raw, lv_color_hex(COL_MUTED), 0);
lv_obj_set_style_text_font(lbl_raw, &lv_font_montserrat_14, 0);
lv_obj_align(lbl_raw, LV_ALIGN_TOP_MID, 0, 168);
btn_reset = lv_button_create(scr);
lv_obj_set_size(btn_reset, UI_HOR_RES - 48, 40);
lv_obj_align(btn_reset, LV_ALIGN_TOP_MID, 0, 192);
style_btn(btn_reset, COL_BTN);
lv_obj_add_event_cb(btn_reset, on_reset, LV_EVENT_CLICKED, nullptr);
lbl_reset = lv_label_create(btn_reset);
lv_label_set_text(lbl_reset, "Reset");
lv_obj_set_style_text_color(lbl_reset, lv_color_hex(COL_INK), 0);
lv_obj_set_style_text_font(lbl_reset, &lv_font_montserrat_20, 0);
lv_obj_center(lbl_reset);
ui_refresh();
}