基于ESP32-S2平台实现游戏摇杆控制LCD屏幕显示
基于ESP32-S3平台实现了利用游戏摇杆能够控制LCD屏幕上一个正方形的运动。
标签
嵌入式系统
2023寒假在家练
Owen
更新2023-03-27
603

0 项目要求

游戏手柄控制LCD上的信息

  • IO扩展板上有一个用X、Y二轴电位计制作的游戏手柄,这两个电位计串接在一个振荡电路中,两个电位计的变化会改变阻值,从而改变生成的PWM信号的频率和占空比。
  • 通过单片机的IO端口测量这个PWM信号的频率和占空比的变化,就能够判断出电阻的变化,进而判断出游戏手柄的方向变化。

要求:本任务需要用ESP32板测量IO扩展板上的PWM信号,在LCD上以图形化的方式显示游戏摇杆的变化,通过游戏摇杆的拨动,能够触及LCD的全屏幕。

1 开发环境搭建

采用PlatformIO平台进行开发。该平台以VSCode插件的形式呈现,无论是编写代码,上板调试都十分的方便快捷,故采用该平台完成项目的开发。

在PlatformIO首次创建项目时会下载一系列的硬件开发库,如果不使用众所周知的方法,整个过程非常耗时。因此,我采用了离线安装的方法,教程参见下方的链接。

【Arduino IDE太难用?5分钟"离线"安装PlatformIO,无需等待,编程体验原地起飞】 https://www.bilibili.com/video/BV1xY4y1b7un/?share_source=copy_web&vd_source=b761846b0a45a5a9d73b01fe244a9a11

2 项目设计思路

需要获取摇杆移动的方向,并让LCD屏幕上的正方形沿着摇杆的方向运动。

2.1 PWM波形捕获

首先要获知摇杆运动的方向。经过外围电路的设计,游戏摇杆能够输出一路PWM波形。当摇杆沿横向运动时,PWM波的频率会发生变化。当摇杆沿纵向运动时,PWM波的占空比会发生变化,因此需要设计程序来检测PWM波的频率与占空比。

2.1.1 PWM波频率测量

使用定时器0产生计数器数满的中断,每20us检测一次PWM波的频率和占空比。使用脉冲计数器(pcnt)来检测PWM波的频率。将脉冲计数器设置为上升沿计数模式。每20us内的PWM波形的上升沿个数近似与PWM波周期个数相同,因此可以用pcnt的上升沿计数来代替PWM波的频率。

使用ESP-IDF中的pcnt库函数对pcnt进行配置,配置代码如下:

pcnt_config_t pcntFreqConfig = { };                        // Instance of pulse counter
  pcntFreqConfig.pulse_gpio_num = PCNT_INPUT_SIG_IO;        // pin assignment for pulse counter = GPIO 15
  pcntFreqConfig.pos_mode = PCNT_COUNT_INC;                  // count rising edges (=change from low to high logical level) as pulses
  pcntFreqConfig.counter_h_lim = PCNT_H_LIM_VAL;             // set upper limit of counting 
  pcntFreqConfig.unit = PCNT_FREQ_UNIT;                      // select ESP32 pulse counter unit 0
  pcntFreqConfig.channel = PCNT_CHANNEL_0;                   // select channel 0 of pulse counter unit 0
  pcnt_unit_config(&pcntFreqConfig);                         // configur rigisters of the pulse counter

  pcnt_counter_pause(PCNT_FREQ_UNIT);                        // pause puls counter unit
  pcnt_counter_clear(PCNT_FREQ_UNIT);                        // zero and reset of pulse counter unit

  pcnt_event_enable(PCNT_FREQ_UNIT, PCNT_EVT_H_LIM);         // enable event for interrupt on reaching upper limit of counting
  pcnt_isr_register(CounterOverflow, NULL, 0, &user_isr_handle);  // configure register overflow interrupt handler
  pcnt_intr_enable(PCNT_FREQ_UNIT);                          // enable overflow interrupt

  //pcnt_set_filter_value(PCNT_FREQ_UNIT, PCNT_FILTER_VAL);    // set damping, inertia 
  pcnt_filter_enable(PCNT_FREQ_UNIT);                        // enable counter glitch filter (damping)

  pcnt_counter_resume(PCNT_FREQ_UNIT);                       // resume counting on pulse counter unit

每进入定时器0中断后,读取pcnt计数器中的值将其作为频率的替代值并对pcnt清零。代码如下所示。

2.1.2 PWM波占空比测量

占空比测量主要依赖于定时器1与GPIO中断来实现。由于PWM波的周期可以由频率得知,而频率测量方法已经由上文给出,因此只需测量PWM波维持在高电平的时间,具体测量思路如下图所示:

FlB84bXpVHYFG2D5kpIyUnqiqlWv

2.2 LCD屏幕的编程

采用基于Arduino库的TFT_eSPI库对LCD屏幕进行编程。

首先修改配置文件User_setup.h

选择屏幕的型号

#define ST7735_DRIVER      // Define additional parameters below for this display

在对应的型号处更改屏幕的横向与纵向像素个数

// For ST7789, ST7735, ILI9163 and GC9A01 ONLY, define the pixel width and height in portrait orientation
// #define TFT_WIDTH  80
 #define TFT_WIDTH  128
// #define TFT_WIDTH  172 // ST7789 172 x 320
// #define TFT_WIDTH  240 // ST7789 240 x 240 and 240 x 320
// #define TFT_HEIGHT 160
 #define TFT_HEIGHT 128
// #define TFT_HEIGHT 240 // ST7789 240 x 240
// #define TFT_HEIGHT 320 // ST7789 240 x 320
// #define TFT_HEIGHT 240 // GC9A01 240 x 240

使能此项,原因如注释所写

// For ST7735 ONLY, define the type of display, originally this was based on the
// colour of the tab on the screen protector film but this is not always true, so try
// out the different options below if the screen does not display graphics correctly,
// e.g. colours wrong, mirror images, or stray pixels at the edges.
// Comment out ALL BUT ONE of these options for a ST7735 display driver, save this
// this User_Setup file, then rebuild and upload the sketch to the board again:

// #define ST7735_INITB
// #define ST7735_GREENTAB
// #define ST7735_GREENTAB2
 #define ST7735_GREENTAB3
// #define ST7735_GREENTAB128    // For 128 x 128 display
// #define ST7735_GREENTAB160x80 // For 160 x 80 display (BGR, inverted, 26 offset)
// #define ST7735_ROBOTLCD       // For some RobotLCD arduino shields (128x160, BGR, https://docs.arduino.cc/retired/getting-started-guides/TFT)
// #define ST7735_REDTAB
// #define ST7735_BLACKTAB
// #define ST7735_REDTAB160x80   // For 160 x 80 display with 24 pixel offset

在ESP32开发板位置处修改屏幕引脚

// For ESP32 Dev board (only tested with GC9A01 display)
// The hardware SPI can be mapped to any pins

#define TFT_MOSI 21 // In some display driver board, it might be written as "SDA" and so on.
#define TFT_SCLK 41
#define TFT_CS   13  // Chip select control pin
#define TFT_DC   17  // Data Command control pin
#define TFT_RST  18  // Reset pin (could connect to Arduino RESET pin)
//#define TFT_BL   22  // LED back-light

修改RGB颜色顺序

  #define TFT_RGB_ORDER TFT_BGR  // Colour order Blue-Green-Red

使用如下的函数就能在坐标x,y处绘制边长为w,h的长方形了

void TFT_eSPI::fillRect(int32_t x, int32_t y, int32_t w, int32_t h, uint32_t color)

2.3 使用摇杆控制正方形

使用串口调试发现摇杆在X方向上的位移量和PWM波频率近似呈线性变化,Y轴方向上的位移量和PWM波占空比近似呈线性变化。因此可以通过PWM波的频率和占空比通过线性函数反算出游戏摇杆偏移量进而得到LCD上正方形的偏移量

整体流程图如下图所示。

FosUXTTxneb59sLE2OPEavHNOMlH

3 问题解决

在实际上板调试后发现,正方形在移动过程中经常出现抖动。画出占空比随时间变化的曲线后发现,PWM波的占空比经常出现因大幅度的跳变而产生的毛刺,这也是导致正方形出现抖动的原因,这可能是由于摇杆的硬件不理想特性造成的。

FsnPzfk4YxYcvWkaLNx88h6vTIt1

采用软件滤波来解决这一问题。具体而言,是限制相邻两次占空比之间的数值变化不能超过某一阈值。如果超过,则强行将最新的一次占空比的值赋值成与上一次占空比数值相等。这种解决方法取得了较好的效果。

4 未来计划

目前屏幕在刷新时会出现闪烁,未来会考虑解决这一问题。

5 工程文件

完整的工程文件包含较多库文件,大小为12MB,超过了附件上传的限制,烦请从下方网盘链接下载。

链接:https://pan.baidu.com/s/1nM4fNh8nwxZLOJy8Nle9mg?pwd=rx7e 
提取码:rx7e 

 

 

团队介绍
大四学生
团队成员
Owen
评论
0 / 100
查看更多
目录
硬禾服务号
关注最新动态
0512-67862536
info@eetree.cn
江苏省苏州市苏州工业园区新平街388号腾飞创新园A2幢815室
苏州硬禾信息科技有限公司
Copyright © 2023 苏州硬禾信息科技有限公司 All Rights Reserved 苏ICP备19040198号