Tiny Mobile Terminal Device Kit.

Related tags

CLI Peak
Overview

说明

本项目是一个超迷你的智能小终端,集成LVGL图像框架、MVC框架、消息框架、WiFi蓝牙能力,未来会加入触摸屏支持。可以作为智能控制器用于实现很多应用。

另外我正在上面实现一个非常小型的3D引擎,可以用于动态显示一些3D模型(就像Dummy示教器中展示的那样)。

非常感谢 https://github.com/FASTSHIFT 开源的X-Track项目,本文是对于X-Track硬件和固件往ESP32平台移植的记录说明。

1. 硬件移植

关于芯片选型

主要考虑MCU的Flash、SRAM、SPI速度,需要满足以下要求:

  • 主频 > 150MHz
  • RAM >= 200KB
  • FLASH >= 512KB
  • SPI速度 >= 50Mbps(60fps刷新率的要求)

lvgl中需要设置LCD buffer,一般设置为屏幕分辨率大小,在本项目中为240x240x2(因为是16bit色深所以每个像素2字节),算下来至少需要112KB的SRAM。

SPI的CLK速度计算如下:240x240x2x8x60=55.296MHz,因此最好是达到50MHz以上的频率才能保证刷新流畅(实际上不使用DMA传输数据的话帧率会更低)。

经过筛选满足以上要求的MCU,综合考虑成本和购买渠道问题,除了官方项目使用的雅特力AT32F403ACGU7主控外,还有两款是比较合适的:STM32F405RGT6、ESP32。

对比优缺点如下:

  • STM32F405的主频不如ESP32高且后者为双核;
  • 外设方面STM32F405更丰富,也支持使用DMA+SPI驱动屏幕;
  • ESP32带WiFi能力,STM32不带;
  • ESP32可以直接基于Arduino生态开发,而STM32一般基于HAL库,移植Arduino较麻烦;
  • STM32可以使用ST-Link方便调试而ESP32只能通过串口打印log调试。

最终选择ESP32-PICO-D4作为移植MCU方案。

2. 固件移植

原工程的架构分层设计比较合理,整体软件架构如下图所示,系统由 HAL、Framework 和 APP 三层组成 :

LVGL 和页面调度

LVGL是开源的嵌入式图形库,其广泛应用嵌入式 GUI 中,提供了基础控件和底层图形渲染能力。

X-TRACK 使用 LVGL 作为图形库,提供用户显示界面,并使用了许多 LVGL 提供的基础控件。例如在地图页面的轨迹显示中使用了 line 控件,地图显示使用了 image 控件,在表盘页面的页面切换选择,使用了 button 控件。由于 LVGL 自带页面管理功能较弱,需要规范页面行为,便于对页面生命周期进行管理。

页面调度器参考 IOS ViewController 进行设计,页面生命周期管理流程图如下:

根据页面当前状态,对页面动作进行管理。例如地图页面的加载,在执行 onViewLoad (页面开始加载)时初始化视图和数据;在 onViewDidAppear(页面即将显示) 执行过渡动画,在动画结束时显示地图容器。

在有外部按键事件触发后,依次执行onViewWillDisappear(页面即将消失)、 onViewDidDisappear (页面消失完成)、onViewDidUnload(页面卸载完成)。

消息框架

消息框架提供数据的分发和处理。其使用订阅发布机制完成,将 HAL 层的接收到的传感器数据发布,转发给对应的订阅者进行数据处理。

以 GPS 为例,GPS 数据处理节点每秒读取一次卫星数据,然后发起 publish ,由消息框架将 GPS 数据推送给订阅者。在运动数据处理节点中订阅 GPS 数据。在收到 GPS 数据之后,运动数据处理节点根据 GPS 数据计算总里程,平均速度等信息。在表盘页面中,拉取运动数据节点信息,将其显示在表盘页面中。

比如下图为 GPS 数据事件回调函数:

屏幕移植

具体移植步骤为:

  1. 将LVGL(使用版本为v8.1)的相关port函数移植到新平台(显示、文件、输入)
  2. 实现HAL层的各个文件

其中第一步中SD卡文件系统的移植遇到问题是用SD库可以读写,而LVGL的文件操作函数不行,后发现原因是lv_port_fatfs.cpp文件中的lv_fs_drv_t fs_drv变量需要改为全局/静态变量,原工程中在函数中声明static在CLion编译器下似乎不起作用。

显示的移植涉及到几个配置文件:Config.hlv_conf.hUser_Setup_Select.hSetup24_ST7789.h

首先根据屏幕型号使用TFT_eSPI库驱动测试好硬件。

TFT_eSPI库速度比其他库快,而且其数据类型和LVGL无缝对接。

这个项目中选择Setup24_ST7789.h这个配置文件,除了GPIO屏幕反向像素顺序设置正确之外,SPI_FREQUENCY也是一个很重要的参数,如前面所计算的,为了是的屏幕刷新率达到60Hz,需要设置这个频率高于50MHz。

然而,对于ESP32来说,其具有2个可用的硬件SPI:HSPIVSPI

SPI0是专用于Flash的缓存,ESP32将连接的SPI Flash设备映射到内存中;SPI1和SPI0 使用相同的硬件线,SPI1用于写入flash芯片。

VSPI是默认的SPI总线,要使用HSPI的话,需要修改以下代码中的MISO为26

 if(sck == -1 && miso == -1 && mosi == -1 && ss == -1) {
     _sck = (_spi_num == VSPI) ? SCK : 14;
     _miso = (_spi_num == VSPI) ? MISO : 12; // 需要改为26
     _mosi = (_spi_num == VSPI) ? MOSI : 13;
     _ss = (_spi_num == VSPI) ? SS : 15;

这是因为,HSPI的默认MISO引脚是12,而12在ESP32中是用于上电时设置flash电平的,上电之前上拉会导致芯片无法启动,因此我们将默认的引脚替换为26或其他引脚。

由数据手册可知,ESP32的SPI时钟是由80MHz的APB_CLK时钟信号分频而来,因此最高支持的频率为80MHz,如果分频的话,库函数会自动选择分配系数来获得最接近于设定频率的整数倍系数。

注意,只有在使用IOMUX时才能获得最高的SPI频率,如果SPI采用GPIO矩阵,则最大频率会限制在26.6MHz。

IOMUX指的是不使用IO-Matrix的映射功能,而是使用默认的MISO、MOSI、CLK引脚,也就是如下图:

屏幕驱动验证完成后,配置LVGL的相关初始化函数,其中lv_conf.h的配置有几点值得注意的:

  • LV_MEM_SIZE的设置

    在Arduino环境中LVGL默认定义LV_MEM_CUSTOM=0,即不使用标准库中的malloc等内存分配函数,而是封装了一个*lv_mem_alloc()函数用于内存申请。这个函数的原理其实是**先在编译的时候申请一块LV_MEM_SIZE大小的数组内存,然后在后面使用lv_mem_alloc()函数的时候,从这块内存中进行分配。*

    因此,LV_MEM_SIZE设置的内存大小是在bss段分配的,这个数值设置过大的话会导致编译链接阶段报错内存不足。

    经测试设置16K就足够了,因此代码中该值为(16 * 1024U)

    如果想在后面屏幕buffer中使用这块内存进行分配,那就需要设置大一点,但是ESP32的Arduino框架中对于申请静态内存的尺寸有限制,因此我们并不使用这里的内存,而是到时候用*malloc()*函动态数申请。

  • lv_disp_draw_buf_init函数中的屏幕buffer设置

    这个buffer可以设置为单buffer或者双buffer,但是双buffer只在使用DMA传输数据的时候可以起作用(刷新缓存和传输数据并行),因此这里只用单buffer。

    理论上buffer的尺寸等于屏幕分辨率是最理想的,可以保证一次刷新整个屏幕,但是由于ESP32的内存大小限制,本代码中最大只能设置为屏幕分辨率的一半。

    最早HoloCubic的代码中并未注意到这一设置,buffer只设置为了240x10,因此导致画面刷新缓慢且有撕裂感。

    关于ESP32内存申请的限制,由于能用的内存实际只有大概300KB,而屏幕完整buffer需要112KB,因此很难在内存中找到连续的那么大片空间,经测试不管是用静态变量申请还是malloc动态申请,都无法成功,因此只能设置为一半大小的buffer。

    在ESP32-PICO-D4上测试发现,如果新建空白工程再用ESP.getMaxAllocHeap(),得到的可用空间是略大于115200B的,但是加入lvgl_init()代码之后就不足115200了,因此修改lvgl_init()函数代码,把lv_mem_init函数中static 变量申请的内存改为动态malloc,即可解决buffer问题。

    引起该问题的原因是,ESP32有多块内存可以映射为dataRAM,总大小是300KB左右,但它们之间是不连续的,最大的一块刚好略大于115200。如果在代码中事先编译的时候分配内存占用了这一块(声明了static变量),或者运行的时候在LVGL申请屏幕buffer之前先被其他地方申请了该块内存导致连续可用heap小于115200,那么屏幕buffer就无法申请成功。因此解决方案是先在代码中将这块最大的heap申请下来给屏幕buffer,再运行其他初始化代码即可完美解决。

    关于ESP32的内存模型更多信息,可以参考文章末尾链接的几篇文章分析。

参考链接

Comments
  • 下载的工程编译后报错,提示没有freertos文件 还有fat文件系统也有错误。

    下载的工程编译后报错,提示没有freertos文件 还有fat文件系统也有错误。

    1.freertos 报错内容


    #include "FreeRTOS.h" ^~~~~~~~~~~~ compilation terminated. In file included from src/App/Accounts/ACT_IMU.cpp:2: src/HAL/HAL.h:9:10: fatal error: FreeRTOS.h: No such file or directory

    2.注释freertos文件后编译报fat 错误。

    lib/SD/src/sd_diskio.cpp:825:18: error: 'ff_diskio_impl_t' does not name a type static const ff_diskio_impl_t sd_impl = { ^~~~~~~~~~~~~~~~ lib/SD/src/sd_diskio.cpp:832:31: error: 'sd_impl' was not declared in this scope ff_diskio_register(pdrv, &sd_impl); ^~~~~~~ lib/SD/src/sd_diskio.cpp:832:31: note: suggested alternative: 'fdiml' ff_diskio_register(pdrv, &sd_impl); ^~~~~~~ fdiml lib/SD/src/sd_diskio.cpp:832:5: error: 'ff_diskio_register' was not declared in this scope ff_diskio_register(pdrv, &sd_impl); ^~~~~~~~~~~~~~~~~~ lib/SD/src/sd_diskio.cpp:832:5: note: suggested alternative: 'lv_disp_drv_register' ff_diskio_register(pdrv, &sd_impl); ^~~~~~~~~~~~~~~~~~ lv_disp_drv_register *** [.pio\build\pico32\libbbe\SD\sd_diskio.cpp.o] Error 1

    opened by givemethree 7
  • 关于CON1 引脚引出问题

    关于CON1 引脚引出问题

    MCU的 GPIO5, GPIO10, GPIO19, GPIO32, GPIO33 五个引脚由CON1引出,其中GPIO32, 33已被I2C总线使用,目前线上有MPU6050,引出可以用于I2C 设备扩展;其余3个IO引脚应该是用于普通IO扩展吧,我看到芯片的GPIO9目前是悬空状态,是不是可以考虑用GPIO9替换GPIO5吗?这样可以实现MCU的UART 1信号引出 增强扩展性,也可以避免意外情况下GPIO5拉低导致MCU无法正常启动。 image

    opened by HanfG 2
  • 9250->6050   适配最新Platform框架

    9250->6050 适配最新Platform框架

    Peak-ESP32-fw(6050) 修改9250程序为6050

    原程序在最新的platformio框架会报FreeRTOS路径错误和sd库中定义错误

    由于platformio框架版本问题会报的错误解决方法:

    HAL.h 文件 #include "FreeRTOS.h"改为 #include "FreeRTOS/FreeRTOS.h"

    lib/SD/src/sd_diskio.cpp 添加头文件 #include "diskio_impl.h"

    opened by txp666 0
  • Some reports of suspected vulnerabilities

    Some reports of suspected vulnerabilities

    hi, great project! I found that in the lv_fs_if/lv_fs_pc.c file, there is no length limit for "oldname" and "newname", and sprintf them directly into a fixed-length stack buffer, which may lead to overflow. Although the filename length is limited to 255 bytes on linux, the path length can be up to 4096 bytes.

    /**
     * Rename a file
     * @param drv pointer to a driver where this function belongs
     * @param oldname path to the file
     * @param newname path with the new name
     * @return LV_FS_RES_OK or any error from 'fs_res_t'
     */
    static lv_fs_res_t fs_rename (lv_fs_drv_t * drv, const char * oldname, const char * newname)
    {
    	(void) drv;		/*Unused*/
    	static char new[512];
    	static char old[512];
    
    	sprintf(old, LV_FS_PC_PATH "/%s", oldname);
    	sprintf(new, LV_FS_PC_PATH "/%s", newname);
    
    	int r = rename(old, new);
    
    	if(r == 0) return LV_FS_RES_OK;
    	else return LV_FS_RES_UNKNOWN;
    }
    
    opened by firmianay 1
  • 采用httpCilent获取天气状况的问题

    采用httpCilent获取天气状况的问题

    在复现peak项目时发现,设备能够成功连接wifi,但获取天气时报错: _handle_error(): [start_ssl_client():205]: (-32512) SSL - Memory allocation failed; 将屏幕分得的缓存尽可能减小后又能成功获取天气数据,判断可能是内存分配问题导致无法正常进行ssl_cilent,但不知道该如何进行修改,请各位大佬提提意见~

    opened by pockrt-m 0
  • 页面切换到3D 正方形后回不了SystemInfos页面

    页面切换到3D 正方形后回不了SystemInfos页面

    zhihui你好,

    感谢你的创作和工作,我已经把软件移植到M5 Stack,目前遇到一个小问题,不知道是不是一个Bug。 页面管理众,第一次从SystemInfos 切到 Scene 3D,再切回到SystemInfos,一切ok, 当再次按下按钮切到 Scene 3D之后,无论怎么按按键都切不回SystemInfos 界面,界面一直显示是Sense 3D的图像,但此时按键log告诉我已经在SystemInfos onEvent里面了。

    我单独拉出template和Scene 3D,按照Push - > Pop操作,一样存在问题 ,切一次页面后,停留在template,无法再切入Scene 3D。 不知道是不是页面管理的框架有问题。 本来想再模拟器上来验证,编译了你的代码,应该是路径有问题,我得弄一下。

    不知道你的Peak上是否正常?

    opened by bt5-coder 1
Owner
稚晖
野生钢铁侠本侠。
稚晖
Spitfire is a basic terminal language that can exicute code via the terminal.

Spitfire is a basic terminal language that can exicute code via the terminal. It is easy to learn and runs fast, considering that its just a 300 line c++ file.

jhomas tefferson 0 Nov 18, 2021
Mosh: the mobile shell

Mosh: the mobile shell Mosh is a remote terminal application that supports intermittent connectivity, allows roaming, and provides speculative local e

Mosh (mobile shell) 11.3k Dec 4, 2022
Small header only C++ library for writing multiplatform terminal applications

Terminal Terminal is small header only library for writing terminal applications. It works on Linux, macOS and Windows (in the native cmd.exe console)

Jupyter Xeus 263 Dec 1, 2022
:computer: C++ Functional Terminal User Interface. :heart:

FTXUI Functional Terminal (X) User interface A simple C++ library for terminal based user interface. Demo: Feature Functional style. Inspired by [1] a

Arthur Sonzogni 3.9k Nov 30, 2022
A little UNIX-inspired terminal application for the Numworks Calculator (not using escher).

L.E. Terminal (let for short) is a little UNIX-inspired terminal for the Numworks Calculator.

Cacahuète Sans Sel 20 Aug 31, 2022
Draw sequence diagram in text from terminal.

sequence-diagram-cli Draw seqence diagram from terminal.

null 44 Nov 26, 2022
Terminal calculator made for programmers working with multiple number representations, sizes, and overall close to the bits

Programmer calculator The programmer calculator is a simple terminal tool designed to give maximum efficiency and flexibility to the programmer workin

romes 174 Nov 22, 2022
X terminal emulator rendering through OpenGL ES Compute Shaders

Zutty is a terminal emulator for the X Window System, functionally similar to several other X terminal emulators such as xterm, rxvt and countless others

Tom Szilagyi 252 Dec 3, 2022
The new Windows Terminal and the original Windows console host, all in the same place!

The new Windows Terminal and the original Windows console host, all in the same place!

Microsoft 86.2k Nov 28, 2022
n³ The unorthodox terminal file manager

n³ The unorthodox terminal file manager

Mischievous Meerkat 15.3k Nov 30, 2022
Graphs the activity of a chia harvester in a linux terminal.

Chia Harvest Graph Monitor for Chia Harvesting Introduction The chiaharvestgraph tool will graph Chia Harvesting activity in a linux terminal. Use a 2

Bram Stolk 216 Nov 10, 2022
a simple to use linux terminal

a simple to use linux terminal

notaweeb 7 Feb 17, 2022
Collection of human friendly terminal interface for git.

A collection of human friendly terminal user interface for git.

Arthur Sonzogni 73 Nov 25, 2022
Simple benchmark for terminal output

TermBench This is a simple timing utility you can use to see how slow your terminal program is at parsing escape-sequence-coded color output. It can b

Casey Muratori 176 Oct 19, 2022
tinytetris - 80x23 terminal tetris

tinytetris - 80x23 terminal tetris

Conor Taylor 2k Dec 1, 2022
Contour - A modern C++ Terminal Emulator

contour is a modern terminal emulator, for everyday use. It is aiming for power users with a modern feature mindset.

Contour Terminal Emulator 1k Nov 24, 2022
A C, C++ and Rust library to draw graphics with pixels in the terminal

A library to draw graphics with pixels in the terminal Who needs a GUI when you have a terminal ? Building To generate libpluto.a, run: $ make To ins

null 69 Nov 7, 2022
📺🗿 Terminal graphics for the 21st century.

???? Chafa is a command-line utility that converts all kinds of images, including animated GIFs, into sixel or ANSI/Unicode character output that can be displayed in a terminal.

Hans Petter Jansson 1.8k Nov 29, 2022
Simple Unix Terminal Football Manager-like game.

Superleage 2020/2021 It is a "work in progress" simple game based on some mechanics of Football Manager. The game is in a very early stage of Developm

sewe2000 2 Oct 14, 2021