基于ESP32的加速度传感器控制彩灯
利用拓展版上的三轴加速度传感器,将读出的数值显示在屏幕上并控制RGB彩灯出现不同的颜色,在板子静置30秒后,彩灯可以周期性规律变化
标签
显示
ESP32
2023寒假在家练
刘艾陇
更新2023-03-27
西安电子科技大学
495

硬禾项目

项目介绍

  • 利用拓展板上的三轴加速度传感器,将读出传感器的数值显示在屏幕上
  • 使用三轴加速度控制RGB彩灯出现不同颜色
  • 在板子静置30秒后,要求彩灯规律周期变化

设计思路

  • 使用FreeRTOS进行模块化处理
    1. LCD终端显示任务
    2. LED显示任务
    3. 加速度计任务
  • 加速度计任务

加速度计芯片选用恩智浦公司研发的MMA7600FC,其输出协议为数字I²C,可实现采样频率从每秒1次到120次,拥有3轴1.5 g MEMS传感器和CMOS接口控制器集成在同一个封装中。

在加速度计任务中,使用100Hz的频率对三轴加速度数据进行持续读取,范围为[-32,31],同时对外提供加速度数据接口以供其他任务访问加速度计数据。

  • LCD终端显示任务

LCD屏幕驱动采用ST7789芯片,使用4线SPI进行通信。屏幕分辨率为128x128像素,我们配置选择为262K 16位真彩模式。对基本数字和字符按照屏幕显示配置取模,存放于C文件中以数组形式保存。在实现字符显示时,根据ASCII码对数据进行查找选择,使用绘点的方式对字符数组进行逐个绘制,从而显示在屏幕上。该任务以50Hz的频率运行,循环读取三轴加速度接口,将其使用sprintf函数转换为字符串显示并打印在屏幕上。

  • LED显示任务

LED为三通道RGB彩灯,可使用PWM模式对彩灯亮度进行控制以实现各种颜色的组合。该任务以50Hz的频率运行,读取加速度计接口提供的数据,将其最大最小归一化后,映射到RGB三通道各自的PWM占空比上,以实现将板子朝向不同摆放时,手持板子转到不同方位彩灯颜色跟随变化。 同时,对加速度数据使用滑动时间窗口思想,读取相邻两次各轴加速度的差值进行循环限幅,设置波动阈值检测板子是否处于静止状态,在30s后检测到静止状态将对LED灯进行循环规律闪烁。

软件流程图

代码控制思路利用在线流程图绘制网站展示如下:

FgEm5zMyAWVeg-AuCvGCZ2VxaJEf

硬件介绍

  1. MMA7600FC加速度芯片,由恩智浦公司开发,具有6bit精度的三轴加速度计芯片,使用IIC协议进行数据通信。可实现采样频率从每秒1次到120次,拥有3轴1.5 g MEMS传感器和CMOS接口控制器集成在同一个封装中。
  2. ST7789芯片,用于单片驱动262K色图像TFTLCD, 包含 7202403色) x 320 线输出,可以直接以SPI协议, 或者8位/9位/16位/18位并行连接外部控制器. 显示数据存储在片内240 320 18 bits内存中, 显示内存的读写不需要外部时钟驱动。
  3. LED彩灯为RGB三通道彩灯,可进行PWM控制,电路使用MOS管控制,为低电平有效。
  4. 主控选用ESP32-S2模组,,Xtensa® 32-bit LX7 单核处理器,时钟频率高达 240 MHz,支持多种低功耗工作状态:精细时钟门控、动态电压时钟频率调节,具有完整的IIC和SPI以及PWM函数接口,可在Ubantu环境下使用IDE进行编程,便于用户直接调用,快速配置。

实现的功能

  • 将板子朝向不同摆放时,屏幕显示的数字不同。

FoZg3zGi-YtklmUyEDn2XDCpHC2gFs7AaDkrJk_Fi0bSZK35TykTsoFK

  • 将板子朝向不同摆放时,手持板子转到不同方位彩灯颜色跟随变化。
  • 在板子静置30秒后,彩灯的颜色呈现周期变化。

FrEJXm6crPP3iCj72FAnvNNXP-HEFi46xI06svsY5MRYYLjfvvjeiRX9Fi2Naj3sTxRxiF4YGCsps1lB26un

FoHfTgybhAmMLVHIWUjH0MJsKQItFpSVcJqwZCjIxATgDHgSjKX7hqfKFu2b6oDfpQ90xHj1qBqJ7T__VIla

FoDx-V8ux60P8Z3p9UehPnkWPrIPFi6rv7zoRvIsj2VQ5OPhUEteDHwsFktjpSS2C16t9jKcLr9lKAxU2XhK

代码说明

  • main.c文件
//main.c文件
//主函数任务初始化
mma_task_init();
led_task_init();
lcd_task_init();
  • led.c文件
//led.c文件
//led任务
static void led_task(void * arg) {
    uint32_t count = 0; //30秒计数器
    int8_t x = 0, y = 0, z = 0; //x、y、z轴三轴加速度
    while (1) {
        count++;
        x = get_mma7600fc_x();
        y = get_mma7600fc_y();
        z = get_mma7600fc_z();
        //检测30s内是否振动,是则根据加速度计数值变换彩灯颜色;否则对彩灯颜色
        进行周期性变换
        if (get_mma7600fc_shake()) {
            count = 0;
            clear_mma7600fc_shake();
        }
        if (count >= 30000 / 20) {
            led_loop();
            vTaskDelay(20 / portTICK_PERIOD_MS);
        } else {
            set_color(x, y, z);
        }
        vTaskDelay(20 / portTICK_PERIOD_MS);
    }
}
  • mma7600fc.c文件
//mma7600fc.c文件
//加速度计任务
static void mma_task(void * arg) {
    int8_t pr_x = 0, pr_y = 0, pr_z = 0; //上一次加速度值
    int8_t del_x = 0, del_y = 0, del_z = 0; //两次加速度误差值
    while (1) {
        mma7600fc.x = (int)(MMA7660_GetResult(MMA7660_XOUT) & 0x3f) - 32;
        mma7600fc.y = (int)(MMA7660_GetResult(MMA7660_YOUT) & 0x3f) - 32;
        mma7600fc.z = (int)(MMA7660_GetResult(MMA7660_ZOUT) & 0x3f) - 32;
        //震动检测,需要循环限幅
        del_x = loop_caculate(((int) mma7600fc.x - pr_x), -32, 31);
        del_y = loop_caculate(((int) mma7600fc.y - pr_y), -32, 31);
        del_z = loop_caculate(((int) mma7600fc.z - pr_z), -32, 31);
        if (del_x > SHAKE_DELTA || del_y > SHAKE_DELTA || del_z > SHAKE_DELTA) {
            mma7600fc.shake = 1;
        }
        pr_x = mma7600fc.x;
        pr_y = mma7600fc.y;
        pr_z = mma7600fc.z;
        vTaskDelay(10 / portTICK_PERIOD_MS);
    }
}
  • st7789.c文件
//st7789.c文件
//LCD显示任务
static void lcd_task(void * arg) {
    int8_t x = 0, y = 0, z = 0;
    char show_buffer[128] = {
        '\0'
    };
    while (1) {
        //调用接口获取加速度计数值
        x = get_mma7600fc_x();
        y = get_mma7600fc_y();
        z = get_mma7600fc_z();
        //制作屏幕显示字符串
        sprintf(show_buffer, "X-axis=%d \nY-axis=%d \nZ-axis=%d \n", x, y, z);
        //调用屏幕显示函数
        lcd_show_string(0, 0, 127, 127, show_buffer, 16, 0);
        vTaskDelay(20 / portTICK_PERIOD_MS);
    }
}

困难与解决方案

1.LCD部分颜色显示与芯片手册不对应,怀疑是LCD裸屏电路硬件管脚问题,暂时未解决。

2.彩灯PWM通道原先直连在串口0上,对于ESP32来说,串口0是不能定义为其他管脚的,但考虑到题目还要求控制这个彩灯。解决方案:使用杜邦线链接未使用的管脚到LED RGB三个控制管脚上,如下图所示:

Fi7iC7dRjAWArrALFI6K8kzXEuLb

3.拓展版下载电路部分,无法自动做到软件重启。调试的时候会导致无法编译调试一条龙,需要点击reset按键进行复位操作。同时每次开发板上电后都需要硬件按键复位代码才能启动。在虚拟机Ubantu系统下调试,频繁的USB口断连与链接或导致USB口偶尔出现异常问题。
改进方案是前期未使用PWM调试LED灯时可以在串口0位置飞线链接一块CH340进行调试,增加调试的流畅度。但考虑到使用LED灯与使用串口相矛盾,因此在调试led灯相关任务时务必不能使用串口进行调试打印。

 计划或建议

1.改进拓展板,将LED灯的RGB三个管脚与ESP32՟S2的普通GPIO口相连。

2.选择一款稳定的由ST7789芯片驱动的屏幕对自己写的屏幕驱动做测试,检查颜色显示异常是否是硬件原因,如果不是则进行进一步修改查错。

3.改进拓展版下载电路部分,无法自动做到软件重启。调试的时候会导致无法编译调试一条龙,需要点击reset按键进行复位操作。同时每次开发板上电后都需要硬件按键复位代码才能启动。
 

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