用M5Stick C Plus实现电子沙漏
2022暑期在家一起练-用M5Stick C Plus实现电子沙漏
标签
嵌入式系统
显示
暑期一起练
M5 Stick
MDYi
更新2022-09-02
北京交通大学
1410

0.目录

  1. 项目要求

  2. 实现功能

  3. 项目分析

  4. 实现思路

  5. 灯板实现

  6. 实物展示

  7. 心得体会

  8. 附件

 

1.项目要求

可以定时的电子沙漏,要求设置不同的时长,在LCD屏幕上显示时间,在灯板上显示沙漏效果。

 

2.实现功能

  • 通过按键设置定时时长,最大支持99分99秒。

  • 在LCD上显示当前时间,时间分辨率为100ms。

  • 在灯板上实现沙漏效果。

 

3.项目分析

M5StickC PLUS 是M5StickC的大屏幕版本,主控采用ESP32-PICO-D4模组,具备蓝牙4.2与WIFI功能,小巧的机身内部集成了丰富的硬件资源,如红外、RTC、麦克风、LED、IMU、按键、蜂鸣器、PMU等,在保留原有M5StickC功能的基础上加入了无源蜂鸣器,同时屏幕尺寸升级到1.14寸、135*240分辨率的TFT屏幕。

FvUAW8hKcrsNEP-l3nQw6zyRma-n

项目中使用了2个按键、TFT-LCD显示屏以及G0、G25、G26三个IO口用于连接灯板控制。

 

4.实现思路

项目使用VS CodePlatformIO进行开发,开发板选择espressif32。在platformio.ini中配置下载波特率为upload_speed = 1500000,否则可能无法下载成功。

4.1 LCD驱动

安装bodmer/TFT_eSPI@2.4.30库,进行TFT-LCD屏幕的控制,修改User_Setup.h中屏幕配置,主要内容如下:

#define TFT_WIDTH 135
#define TFT_HEIGHT 240
​
#define TFT_MOSI 15
#define TFT_SCLK 13
#define TFT_CS 5
#define TFT_DC 23
#define TFT_RST 18

4.2 电源管理

M5Stick的电源结构如下图。

Fh5oNy5niA5K5XMI4BSL2z1yFZyu

主控ESP32通过i2c与电源管理芯片AXP192连接,需要先使能AXP192的输出端口LDO2才能打开LCD屏幕背光,否则无法显示内容。

FiArLSpLDGGEYmlK6lF46Sw-gU9J

直接移植M5Stick官方Demo中的AXP192库,通过以下代码初始化并使能AXP192输出。

AXP192 Axp = AXP192();
Axp.begin();

4.3 中文字库

LCD中的中文采用仿宋字体,时间显示采用数码管字体,英文使用TFT_eSPI的默认字体,字库制作见下文。

字库主要通过Processing实现,官网下载速度较慢,可以在CSDN上找绿色版。程序需要在无特殊字符的路径下才能打开。字库配置的主要步骤参见使用Arduino TFT_eSPI库自定义中文字库 - 哔哩哔哩 (bilibili.com)

4.4 定时器

沙漏的定时采用定时器中断进行,定时器每100ms中断一次,将标志位置1。在主循环中判断标志位进行时间处理。

//定时器时间(ms)
#define TIMER_SET_MS 100
​
//定时器变量
hw_timer_t *timer = NULL;
portMUX_TYPE timerMux = portMUX_INITIALIZER_UNLOCKED;
​
//定时器中断函数
void IRAM_ATTR InterruptProc_OnTimer()
{
  portENTER_CRITICAL_ISR(&timerMux);
  flag_timer = true;
  portEXIT_CRITICAL_ISR(&timerMux);
  timerAlarmDisable(timer);
}

定时器开关通过以下函数:

timerAlarmEnable(timer);    //打开定时器
timerAlarmDisable(timer);   //关闭定时器
 

4.5 按键

按键的读取同样采用中断方式,按键消抖时间200ms,配置引脚为内部上拉,下降沿触发中断。

//引脚定义
#define GPIO_KEY_A 37
#define GPIO_KEY_B 39
​
//按键防抖时间
#define KEY_DELTA_TIME 200
​
//按键按下时间
volatile unsigned long triggerTime_KeyA = 0; //按键按下,第一次触发中断的时刻
volatile unsigned long triggerTime_KeyB = 0; //按键按下,第一次触发中断的时刻
​
//按键初始化
pinMode(GPIO_KEY_A, INPUT_PULLUP); //设置引脚输入模式并打开内部上拉
pinMode(GPIO_KEY_B, INPUT_PULLUP); //设置引脚输入模式并打开内部上拉
​
//按键中断初始化
attachInterrupt(GPIO_KEY_A, InterruptProc_KEY_A, FALLING); // 由高变低时触发中断
attachInterrupt(GPIO_KEY_B, InterruptProc_KEY_B, FALLING); // 由高变低时触发中断
​
// 按键A中断函数
void InterruptProc_KEY_A()
{
    if (millis() - triggerTime_KeyA > KEY_DELTA_TIME)
    {
        detachInterrupt(GPIO_KEY_A);
        flag_keyA = true;
    }
}
​
// 按键B中断函数
void InterruptProc_KEY_B()
{
    if (millis() - triggerTime_KeyB > KEY_DELTA_TIME)
    {
        detachInterrupt(GPIO_KEY_B);
        flag_keyB = true;
    }
}

 

5.灯板实现

灯板上共有2组接口J1与J2,J1与上级控制器连接,J2与下级灯板连接,实现灯板的级联。

Fj5HQtwmNU-7NCmNtCLmpPG7y34m

本次实际到手的灯板为黑色PCB版本。

VCC与GND分别连接M5接口中的5V输出与GND,其他引脚配置如下:

#define GPIO_DIN 25
#define GPIO_RCK 26
#define GPIO_SCK 0

编写HC595库实现HC595芯片的驱动,主要函数为void HC595_Write(uint8_t data, bool fresh)。

void HC595_Write(uint8_t data, bool fresh)
{
    for (int i = 0; i < 8; i++)
    {
        digitalWrite(GPIO_DIN, (data >> i) & 0x01);
        digitalWrite(GPIO_SCK, LOW);
        digitalWrite(GPIO_SCK, HIGH);
    }
    if (fresh == true)
    {
        HC595_Refresh();
    }
}

在此基础上编写LED_Board库实现灯板的控制。

灯板可以通过点扫描与行扫描实现任意图形的刷新,通过视觉暂留使得人眼能看到完整的图形,由于点扫描的效率较慢,因此最终选择行扫描。

void LED_8x8_WriteRow(uint8_t data, uint8_t rowNum)
{
    HC595_Write(0x01 << (7 - rowNum), false);
    HC595_Write(data, false);
}
​
void LED_8x16_DrawPicByRow(uint8_t *datas)
{
    for (int i = 0; i < 8; i++)
    {
        if ((datas[i] != 0) || (datas[i + 8] != 0))
        {
            LED_8x16_Clear();
            LED_8x8_WriteRow(datas[i + 8], i);
            LED_8x8_WriteRow(datas[i], i);
            HC595_Refresh();
        }
    }
    LED_8x16_Clear();
}

灯板的沙漏共有9种情况,提前设置将像素点内容写入数组,计时时间每进行12.5%进行一次变换。

// 沙漏效果
uint8_t LED_State1[16] = {0x01, 0x03, 0x07, 0x0F, 0x1F, 0x3F, 0x7F, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
uint8_t LED_State2[16] = {0x00, 0x01, 0x03, 0x07, 0x0F, 0x1F, 0x3F, 0x7F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01};
uint8_t LED_State3[16] = {0x00, 0x00, 0x01, 0x03, 0x07, 0x0F, 0x1F, 0x3F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x03};
uint8_t LED_State4[16] = {0x00, 0x00, 0x00, 0x01, 0x03, 0x07, 0x0F, 0x1F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x03, 0x07};
uint8_t LED_State5[16] = {0x00, 0x00, 0x00, 0x00, 0x01, 0x03, 0x07, 0x0F, 0x00, 0x00, 0x00, 0x00, 0x01, 0x03, 0x07, 0x0F};
uint8_t LED_State6[16] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x03, 0x07, 0x00, 0x00, 0x00, 0x01, 0x03, 0x07, 0x0F, 0x1F};
uint8_t LED_State7[16] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x03, 0x00, 0x00, 0x01, 0x03, 0x07, 0x0F, 0x1F, 0x3F};
uint8_t LED_State8[16] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x03, 0x07, 0x0F, 0x1F, 0x3F, 0x7F};
uint8_t LED_State9[16] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x03, 0x07, 0x0F, 0x1F, 0x3F, 0x7F, 0xFF};
 

 

6.实物展示

沙漏效果参见B站视频。

FtqXLirTEZY4vzk7GVxmNWmJgfH8

 

7.心得体会

  • M5的按键手感较差,单手操作时无法按动。

  • 灯板的像素点较小,实现起来的效果较差。

  • M5Stick的外设丰富,可以满足日常DIY的需求。

 

8.附件

附件见百度网盘

链接:https://pan.baidu.com/s/1iO__s-6gfKX9yP41C5seJg?pwd=w1pk 
提取码:w1pk

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