PaperDIY

PaperDIY 是一款基于 ESP32-S3 的主机,配备 4.7 英寸、960x540 单色墨水屏、16MB Flash 和 8MB PSRAM。

支持以下产品:

PaperDIY

支持的组件

PaperDIY 支持以下组件:

  • Display:通过 M5.Lcd 进行屏幕绘图。

  • Widgets:通过 M5.Widgets 和 widgets 包使用标签等基础 UI 组件。

  • Unit:包含 Unit 驱动的 unit 包。

  • Chain:用于 Chain 设备的 chain 包。

  • usb.device:提供 USB HID 键盘和鼠标支持。

PaperDIY 固件使用 M5GFX 进行显示渲染,未启用 LVGL 和 M5UI。

支持的显示字体

PaperDIY 固件通过 M5.Lcd.FONTS 和 M5.Widgets.FONTS 提供以下 Montserrat 字体:Montserrat12、Montserrat14、Montserrat16、Montserrat18、Montserrat24、Montserrat40、Montserrat44 和 Montserrat48。

固件还提供 AlibabaPuHuiTiCN24、AlibabaSansJA24 和 AlibabaSansKR24,分别用于显示中文、日文和韩文。

板载功能

PaperDIY 支持以下内置功能和外设:

  • 4.7 英寸单色墨水屏,支持竖屏和横屏显示。

  • 通过 BtnA 和 BtnB 进行 按键 输入。

  • 通过 M5PM1 进行 电源管理:读取 USB 电压、电池电压和充电状态,并控制电池充电。

  • TF(microSD)卡存储。

  • Wi-Fi 联网和原生 USB 编程。

墨水屏不带触摸面板和背光。

UiFlow2 示例

按键计数

在 UiFlow2 中打开 paperdiy_button_counter_example.m5f2 项目。

此示例以竖屏显示两个独立的按键计数器。按下 BtnA 或 BtnB,对应的计数器加 1。示例启动时,两个计数器均从 0 开始。

UiFlow2 代码块:

paperdiy_button_counter_example.png

示例输出:

无

充电检测

在 UiFlow2 中打开 paperdiy_charge_detection_example.m5f2 项目。

此示例以毫伏(mV)显示电池电压和 USB 电压,并显示充电状态。示例启动时默认开启电池充电,按下 BtnA 可开启或关闭充电。读数每 15 秒刷新一次,按键后也会立即刷新。

UiFlow2 代码块:

paperdiy_charge_detection_example.png

示例输出:

无

MicroPython 示例

按键计数

此示例以竖屏显示两个独立的按键计数器。按下 BtnA 或 BtnB,对应的计数器加 1。示例启动时,两个计数器均从 0 开始。

MicroPython 代码块:

  1# SPDX-FileCopyrightText: 2026 M5Stack Technology CO LTD
  2#
  3# SPDX-License-Identifier: MIT
  4
  5import os
  6import sys
  7import io
  8import time
  9
 10import M5
 11from M5 import *
 12
 13
 14label_title = None
 15label_btn_a = None
 16label_btn_b = None
 17label_hint = None
 18
 19button_a_count = None
 20button_b_count = None
 21
 22
 23def btna_was_pressed_event(state):
 24    global button_a_count
 25
 26    button_a_count = button_a_count + 1
 27    label_btn_a.setText(str("Button A: " + str(button_a_count)))
 28
 29
 30def btnb_was_pressed_event(state):
 31    global button_b_count
 32
 33    button_b_count = button_b_count + 1
 34    label_btn_b.setText(str("Button B: " + str(button_b_count)))
 35
 36
 37def setup():
 38    global label_title, label_btn_a, label_btn_b, label_hint
 39    global button_a_count, button_b_count
 40
 41    M5.begin()
 42    Widgets.setRotation(0)
 43    Widgets.fillScreen(0xFFFFFF)
 44    label_title = Widgets.Label(
 45        "PaperDIY Button Counter",
 46        30,
 47        40,
 48        1.0,
 49        0x000000,
 50        0xFFFFFF,
 51        Widgets.FONTS.Montserrat24,
 52    )
 53    label_btn_a = Widgets.Label(
 54        "Button A: 0",
 55        30,
 56        240,
 57        1.0,
 58        0x000000,
 59        0xFFFFFF,
 60        Widgets.FONTS.Montserrat40,
 61    )
 62    label_btn_b = Widgets.Label(
 63        "Button B: 0",
 64        30,
 65        400,
 66        1.0,
 67        0x000000,
 68        0xFFFFFF,
 69        Widgets.FONTS.Montserrat40,
 70    )
 71    label_hint = Widgets.Label(
 72        "Press Button A or Button B",
 73        30,
 74        600,
 75        1.0,
 76        0x000000,
 77        0xFFFFFF,
 78        Widgets.FONTS.Montserrat24,
 79    )
 80
 81    BtnA.setCallback(type=BtnA.CB_TYPE.WAS_PRESSED, cb=btna_was_pressed_event)
 82    BtnB.setCallback(type=BtnB.CB_TYPE.WAS_PRESSED, cb=btnb_was_pressed_event)
 83
 84    M5.Display.setEpdMode(M5.Display.EPDMode.EPD_FASTEST)
 85    button_a_count = 0
 86    button_b_count = 0
 87
 88
 89def loop():
 90    M5.update()
 91    time.sleep_ms(10)
 92
 93
 94if __name__ == "__main__":
 95    try:
 96        setup()
 97        while True:
 98            loop()
 99    except (Exception, KeyboardInterrupt) as error:
100        try:
101            from utility import print_error_msg
102
103            print_error_msg(error)
104        except ImportError:
105            print(error)

示例输出:

无

充电检测

此示例以毫伏(mV)显示电池电压和 USB 电压,并显示充电状态。示例启动时默认开启电池充电,按下 BtnA 可开启或关闭充电。读数每 15 秒刷新一次,按键后也会立即刷新。

MicroPython 代码块:

  1import os, sys, io
  2import M5
  3from M5 import *
  4import time
  5
  6
  7label_title = None
  8label_vbat = None
  9label_vbus = None
 10label_enable = None
 11label_state = None
 12label_hint = None
 13
 14
 15charge_enabled = None
 16vbat = None
 17vbus = None
 18next_refresh = None
 19
 20
 21def btna_was_pressed_event(state):
 22    global \
 23        label_title, \
 24        label_vbat, \
 25        label_vbus, \
 26        label_enable, \
 27        label_state, \
 28        label_hint, \
 29        charge_enabled, \
 30        vbat, \
 31        vbus, \
 32        next_refresh
 33    charge_enabled = not charge_enabled
 34    if charge_enabled:
 35        Power.setBatteryCharge(True)
 36        label_enable.setText(str("Charge enable: ON"))
 37    else:
 38        Power.setBatteryCharge(False)
 39        label_enable.setText(str("Charge enable: OFF"))
 40    vbat = Power.getBatteryVoltage()
 41    vbus = Power.getVBUSVoltage()
 42    label_vbat.setText(str((str((str("VBAT: ") + str(vbat))) + str(" mV"))))
 43    label_vbus.setText(str((str((str("VBUS: ") + str(vbus))) + str(" mV"))))
 44    if Power.isCharging():
 45        label_state.setText(str("Charge state: charging"))
 46    else:
 47        label_state.setText(str("Charge state: not charging"))
 48
 49
 50def setup():
 51    global \
 52        label_title, \
 53        label_vbat, \
 54        label_vbus, \
 55        label_enable, \
 56        label_state, \
 57        label_hint, \
 58        charge_enabled, \
 59        vbat, \
 60        vbus, \
 61        next_refresh
 62
 63    M5.begin()
 64    Widgets.setRotation(0)
 65    Widgets.fillScreen(0xFFFFFF)
 66    label_title = Widgets.Label(
 67        "PaperDIY charge detection", 30, 30, 1.0, 0x000000, 0xFFFFFF, Widgets.FONTS.Montserrat24
 68    )
 69    label_vbat = Widgets.Label(
 70        "VBAT: -- mV", 30, 240, 1.0, 0x000000, 0xFFFFFF, Widgets.FONTS.Montserrat24
 71    )
 72    label_vbus = Widgets.Label(
 73        "VBUS: -- mV", 30, 310, 1.0, 0x000000, 0xFFFFFF, Widgets.FONTS.Montserrat24
 74    )
 75    label_enable = Widgets.Label(
 76        "Charge enable: ON", 30, 390, 1.0, 0x000000, 0xFFFFFF, Widgets.FONTS.Montserrat24
 77    )
 78    label_state = Widgets.Label(
 79        "Charge state: --", 30, 470, 1.0, 0x000000, 0xFFFFFF, Widgets.FONTS.Montserrat24
 80    )
 81    label_hint = Widgets.Label(
 82        "Button A toggles battery charge",
 83        30,
 84        600,
 85        1.0,
 86        0x000000,
 87        0xFFFFFF,
 88        Widgets.FONTS.Montserrat24,
 89    )
 90
 91    BtnA.setCallback(type=BtnA.CB_TYPE.WAS_PRESSED, cb=btna_was_pressed_event)
 92
 93    M5.Display.setEpdMode(M5.Display.EPDMode.EPD_FASTEST)
 94    charge_enabled = True
 95    Power.setBatteryCharge(True)
 96    vbat = Power.getBatteryVoltage()
 97    vbus = Power.getVBUSVoltage()
 98    label_vbat.setText(str((str((str("VBAT: ") + str(vbat))) + str(" mV"))))
 99    label_vbus.setText(str((str((str("VBUS: ") + str(vbus))) + str(" mV"))))
100    if Power.isCharging():
101        label_state.setText(str("Charge state: charging"))
102    else:
103        label_state.setText(str("Charge state: not charging"))
104    next_refresh = time.ticks_add((time.ticks_ms()), 15000)
105
106
107def loop():
108    global \
109        label_title, \
110        label_vbat, \
111        label_vbus, \
112        label_enable, \
113        label_state, \
114        label_hint, \
115        charge_enabled, \
116        vbat, \
117        vbus, \
118        next_refresh
119    M5.update()
120    if (time.ticks_diff((time.ticks_ms()), next_refresh)) >= 0:
121        vbat = Power.getBatteryVoltage()
122        vbus = Power.getVBUSVoltage()
123        label_vbat.setText(str((str((str("VBAT: ") + str(vbat))) + str(" mV"))))
124        label_vbus.setText(str((str((str("VBUS: ") + str(vbus))) + str(" mV"))))
125        if Power.isCharging():
126            label_state.setText(str("Charge state: charging"))
127        else:
128            label_state.setText(str("Charge state: not charging"))
129        next_refresh = time.ticks_add((time.ticks_ms()), 15000)
130    time.sleep_ms(10)
131
132
133if __name__ == "__main__":
134    try:
135        setup()
136        while True:
137            loop()
138    except (Exception, KeyboardInterrupt) as e:
139        try:
140            from utility import print_error_msg
141
142            print_error_msg(e)
143        except ImportError:
144            print("please update to latest firmware")

示例输出:

无