驴友花雕 发表于 2025-5-3 19:03:07

【花雕学编程】Arduino动手做(249)--GC9A01动画发射导弹






驴友花雕 发表于 2025-5-3 19:05:12

【花雕学编程】Arduino动手做(249)--GC9A01动画发射导弹






驴友花雕 发表于 2025-5-3 19:11:43

【花雕学编程】Arduino动手做(249)--GC9A01动画发射导弹

【Arduino】189种传感器模块系列实验(资料代码+仿真编程+图形编程)
实验二百四十九:1.28寸圆形彩色TFT显示屏 高清IPS 模块 240*240 SPI接口GC9A01驱动
项目之一百四十四:ESP32+GC9A01之在屏幕上播放发射导弹GIF动画

实验开源代码

/*
【Arduino】189种传感器模块系列实验(资料代码+仿真编程+图形编程)
实验二百四十九:1.28寸圆形彩色TFT显示屏 高清IPS 模块 240*240 SPI接口GC9A01驱动
项目之一百四十四:ESP32+GC9A01之在屏幕上播放发射导弹GIF动画
*/

//       GC9A01---------- ESP32
//       RST ------------ NC(复位引脚,此处未连接)
//       CS ------------- D4(片选引脚,连接到ESP32的D4引脚)
//       DC ------------- D2(数据/命令选择引脚,连接到ESP32的D2引脚)
//       SDA ------------ D23 (green)(主数据输出引脚,连接到ESP32的D23引脚,绿色线)
//       SCL ------------ D18 (yellow)(时钟信号引脚,连接到ESP32的D18引脚,黄色线)
//       GND ------------ GND(接地引脚,连接到ESP32的接地端)
//       VCC -------------3V3(电源引脚,连接到ESP32的3.3V电源)



#include <SPI.h>
#include <TFT_eSPI.h>   // ESP32 专用的 TFT 显示屏库
// 需要通过 Arduino Library Manager 安装
// 使用前需要正确配置屏幕驱动

#include <AnimatedGIF.h>// GIF 动画库
// 通过 Arduino Library Manager 安装
// 负责解码 GIF 并显示到屏幕
AnimatedGIF gif;          // 创建 GIF 处理对象

//预加载的 GIF 图片
#include "images/hyperspace.h"// 星空动画
#include "images/nostromo.h"    // 未来风格 HUD
#include "images/hud_1.h"       // HUD 显示风格 1
#include "images/hud_2.h"       // HUD 显示风格 2
#include "images/hud_5.h"       // HUD 显示风格 5
#include "images/hud_6.h"       // HUD 显示风格 6
#include "images/hud_7.h"       // HUD 显示风格 7
#include "images/darthvader.h"// 达斯·维达角色
#include "images/x_wing.h"      // X 翼战机动画
#include "images/colortest.h"   // 颜色测试动画

// 选择要播放的 GIF 图片
// 只启用一个 GIF,否则 ESP32 可能内存不足
// 如果需要加载多个 GIF,需调整 ESP32 的 Flash 分区
//
// #define GIF_IMAGE colortest
//#define GIF_IMAGE hyperspace
// #define GIF_IMAGE nostromo
// #define GIF_IMAGE darthvader
// #define GIF_IMAGE hud_1
#define GIF_IMAGE hud_2
// #define GIF_IMAGE hud_5
// #define GIF_IMAGE hud_6
// #define GIF_IMAGE hud_7
// #define GIF_IMAGE x_wing

// 创建 TFT 显示对象
TFT_eSPI tft = TFT_eSPI();

void setup() {
Serial.begin(115200);   // 初始化串口,方便调试
tft.begin();            // 启动 TFT 显示屏
tft.setRotation(2);   // 设置屏幕旋转角度(0-3)
tft.fillScreen(TFT_BLACK); // 清空屏幕,填充黑色
gif.begin(BIG_ENDIAN_PIXELS); // 初始化 GIF 处理库(使用大端像素格式)
}

void loop()
{
//尝试打开 GIF 文件
if (gif.open((uint8_t *)GIF_IMAGE, sizeof(GIF_IMAGE), GIFDraw))
{
    Serial.printf("成功打开 GIF;尺寸 = %d x %d\n", gif.getCanvasWidth(), gif.getCanvasHeight());

    tft.startWrite();//开启 TFT 显示屏的写入模式

    // 播放 GIF 每一帧
    while (gif.playFrame(true, NULL))
    {
      yield(); // 让 ESP32 处理其他任务,避免卡死
    }

    gif.close();   // 关闭 GIF 文件
    tft.endWrite(); // 关闭 TFT 写入模式
}
}

驴友花雕 发表于 2025-5-3 19:13:22

【花雕学编程】Arduino动手做(249)--GC9A01动画发射导弹

代码说明

这段代码用于在 ESP32 的 TFT 显示屏上播放 GIF 动画 ,它结合了 TFT_eSPI 库 和 AnimatedGIF 库,能够流畅显示颜色测试等动画。

核心逻辑
1️⃣ 加载 GIF 图像 → 代码包含多个 预加载的 GIF 文件,你可以选择要播放的动画(如 X 翼战机)
2️⃣ 初始化显示屏 → 通过 TFT_eSPI 库 配置屏幕,设置旋转角度,并清空背景色
3️⃣ GIF 播放控制 → 使用 gif.open() 读取 动画数据,然后 逐帧渲染 到屏幕
4️⃣ 流畅显示 GIF → 使用 gif.playFrame(true, NULL) 播放每一帧,并确保 ESP32 运行稳定
5️⃣ 循环播放动画 → GIF 播放完成后 自动重启,形成无缝动态效果

最终效果
ESP32 屏幕上流畅播放 GIF 动画
可以选择不同的 GIF 文件(HUD 界面、科幻角色、星战战机等)
动画不断循环,让显示效果更加生动



驴友花雕 发表于 2025-5-3 19:18:58

【花雕学编程】Arduino动手做(249)---GC9A01卡通猫眼动画






驴友花雕 发表于 2025-5-3 19:24:44

【花雕学编程】Arduino动手做(249)---GC9A01卡通猫眼动画






驴友花雕 发表于 2025-5-3 19:26:09

【花雕学编程】Arduino动手做(249)---GC9A01卡通猫眼动画

【Arduino】189种传感器模块系列实验(资料代码+仿真编程+图形编程)
实验二百四十九:1.28寸圆形彩色TFT显示屏 高清IPS 模块 240*240 SPI接口GC9A01驱动
项目之一百四十五:ESP32+GC9A01之卡通猫眼 (扁平的“2D”颜色)

实验开源代码

/*
【Arduino】189种传感器模块系列实验(资料代码+仿真编程+图形编程)
实验二百四十九:1.28寸圆形彩色TFT显示屏 高清IPS 模块 240*240 SPI接口GC9A01驱动
项目之一百四十五:ESP32+GC9A01之卡通猫眼 (扁平的“2D”颜色)
*/

//       GC9A01---------- ESP32
//       RST ------------ NC(复位引脚,此处未连接)
//       CS ------------- D4(片选引脚,连接到ESP32的D4引脚)
//       DC ------------- D2(数据/命令选择引脚,连接到ESP32的D2引脚)
//       SDA ------------ D23 (green)(主数据输出引脚,连接到ESP32的D23引脚,绿色线)
//       SCL ------------ D18 (yellow)(时钟信号引脚,连接到ESP32的D18引脚,黄色线)
//       GND ------------ GND(接地引脚,连接到ESP32的接地端)
//       VCC -------------3V3(电源引脚,连接到ESP32的3.3V电源)

// 显示的眼睛的大小取决于屏幕的尺寸和分辨率。
// 眼睛图像的宽度固定为 128 像素。在人类的生理结构中,
// 睑裂 (睁开的眼睛的宽度) 大约是 30 毫米。因此,
// 低分辨率、大像素尺寸的显示屏最适合以真实的比例
// 显示眼睛的图像。请注意,显示器制造商通常会标注对角线尺寸,
// 因此一个 128x128 的 1.7 英寸显示屏或 128x160 的 2 英寸显示屏
// 在尺寸上是比较合适的。

// 眼睛的配置设置,包括眼睛的样式、显示器的数量、
// 片选引脚以及眼睛在屏幕上的 X 轴偏移量,都可以在草图的
// "config.h" 选项卡中进行定义。

// 通过在 ESP32 和 STM32 处理器上使用 DMA (直接内存访问,仅适用于 SPI 显示屏),
// 可以显著提高程序的性能 (以每秒传输的帧数,即 fps 来衡量)。
// 应该使用显示器所支持的尽可能高的 SPI 时钟速率。
// 最小推荐速率为 27MHz,一些显示器甚至可以在 40-80MHz 的更高频率下稳定运行。

// 下表列出了在不同处理器上,使用单只默认眼睛 (defaultEye) 时的性能表现:
//                                 无 DMA    有 DMA
// ESP8266 (160MHz CPU) 40MHz SPI   36 fps
// ESP32 27MHz SPI               53 fps   85 fps
// ESP32 40MHz SPI               67 fps    102 fps
// ESP32 80MHz SPI               82 fps    116 fps // 注意:很少有显示器能在 80MHz 下稳定工作
// STM32F401 55MHz SPI               44 fps   90 fps
// STM32F446 55MHz SPI               83 fps    155 fps
// STM32F767 55MHz SPI            136 fps    197 fps

// 当接口是 SPI 时,DMA 可以与 RP2040、STM32 和 ESP32 处理器一起使用。
// 要启用 DMA,请取消注释下一行:
//#define USE_DMA

// 加载 TFT_eSPI 库,用于控制 TFT LCD
#include <SPI.h>      // 包含 Arduino 的 SPI 库
#include <TFT_eSPI.h> // 包含 TFT_eSPI 库
TFT_eSPI tft;         // 创建一个 TFT_eSPI 类的实例,用于控制显示屏

// 在眼睛的渲染过程中,会使用一个像素缓冲区来存储即将绘制的数据。
// BUFFER_SIZE 定义了这个缓冲区的大小,128 到 1024 似乎是一个最佳的范围。
#define BUFFER_SIZE 240

#ifdef USE_DMA
#define BUFFERS 2   // 如果启用了 DMA,则使用 2 个缓冲区进行乒乓操作,提高效率
#else
#define BUFFERS 1   // 如果没有启用 DMA,则只需要 1 个缓冲区
#endif

uint16_t pbuffer; // 声明一个二维数组作为像素渲染缓冲区,每个缓冲区可以存储 BUFFER_SIZE 个 16 位颜色值
bool      dmaBuf   = 0;                  // 一个布尔变量,用于选择当前正在使用的 DMA 缓冲区 (在双缓冲情况下)

// 这个结构体 (struct) 在 config.h 文件中被填充数据。
typedef struct {               // 定义一个名为 eyeInfo_t 的结构体,用于存储每个眼睛的配置信息
int8_tselect;               // 用于连接到每个眼睛的屏幕的片选 (Chip Select, CS) 引脚编号 (int8_t 是 8 位有符号整数)
int8_twink;               // 连接到每个眼睛的“眨眼”按钮的引脚编号 (int8_t)。如果某个眼睛没有眨眼按钮,则设置为 -1。
uint8_t rotation;             // 该眼睛所连接的显示屏的旋转角度 (0-3)。uint8_t 是 8 位无符号整数。
int16_t xposition;            // 眼睛图像在屏幕上的 X 轴位置偏移量 (int16_t 是 16 位有符号整数)。
} eyeInfo_t;

#include "config.h"             // ****** 所有的配置都在这个文件中完成 ******

extern void user_setup(void); // 声明在 user*.cpp 文件中定义的用户自定义初始化函数
extern void user_loop(void);// 声明在 user*.cpp 文件中定义的用户自定义循环函数

#define SCREEN_X_START 0
#define SCREEN_X_END    SCREEN_WIDTH    // 定义屏幕上眼睛图像的 X 轴范围的起始和结束。SCREEN_WIDTH 应该在 config.h 中定义。
#define SCREEN_Y_START 0
#define SCREEN_Y_END    SCREEN_HEIGHT   // 定义屏幕上眼睛图像的 Y 轴范围的起始和结束。SCREEN_HEIGHT 应该在 config.h 中定义。

// 使用一个简单的状态机来控制眼睛的眨眼 (blink) 和单眼眨眼 (wink) 动作:
#define NOBLINK 0         // 定义一个状态:当前没有进行任何眨眼动作
#define ENBLINK 1         // 定义一个状态:眼睑当前正在闭合 (Engaging Blink)
#define DEBLINK 2         // 定义一个状态:眼睑当前正在张开 (Disengaging Blink)
typedef struct {               // 定义一个名为 eyeBlink 的结构体,用于存储每个眼睛的眨眼状态信息
uint8_tstate;         // 当前的眨眼状态 (NOBLINK, ENBLINK, DEBLINK)
uint32_t duration;      // 当前眨眼状态的持续时间 (以微秒为单位)。uint32_t 是 32 位无符号整数。
uint32_t startTime;   // 上次眨眼状态发生改变的时间 (以微秒为单位)。
} eyeBlink;

struct {                     // 定义一个匿名结构体,用于存储每个眼睛的特定信息。eye 数组的每个元素都是这个结构体。
int16_t    tft_cs;         // 连接到每个显示屏的片选 (Chip Select) 引脚编号
eyeBlink   blink;          // 一个 eyeBlink 结构体,存储该眼睛的当前眨眼状态
int16_t    xposition;   // 该眼睛的图像在屏幕上的 X 轴位置
} eye;            // 声明一个名为 eye 的数组,其大小由 NUM_EYES (在 config.h 中定义) 决定。每个元素存储一只眼睛的信息。

uint32_t startTime;   // 用于记录程序启动或上次帧率计算的时间,以便计算每秒帧数 (FPS)。

// 初始化 -- 在启动时运行一次 --------------------------------------------------
void setup(void) {
Serial.begin(115200); // 初始化串口通信,波特率为 115200
//while (!Serial);    // 如果需要等待串口连接,则取消注释此行
Serial.println("Starting"); // 通过串口打印 "Starting"

#if defined(DISPLAY_BACKLIGHT) && (DISPLAY_BACKLIGHT >= 0)
// 如果定义了 DISPLAY_BACKLIGHT 并且其值大于等于 0 (表示使用了背光控制引脚)
Serial.println("Backlight turned off"); // 通过串口打印 "Backlight turned off"
pinMode(DISPLAY_BACKLIGHT, OUTPUT);// 将背光控制引脚设置为输出模式
digitalWrite(DISPLAY_BACKLIGHT, LOW); // 将背光引脚拉低,通常表示关闭背光
#endif

// 调用用户在 user_setup() 函数中定义的任何附加初始化功能
user_setup();

// 初始化眼睛。这个函数可能会设置所有片选引脚为低电平,以便后续的 tft.init() 可以正常工作。
initEyes(); // 这个函数应该在其他地方定义 (例如在 eye_functions.cpp 中)

// 初始化 TFT 显示屏
Serial.println("Initialising displays"); // 通过串口打印 "Initialising displays"
tft.init();                               // 调用 TFT_eSPI 库的初始化函数

#ifdef USE_DMA
tft.initDMA(); // 如果定义了 USE_DMA,则初始化 DMA 功能
#endif

// 拉高片选引脚,以便可以单独配置每个显示屏
digitalWrite(eye.tft_cs, HIGH); // 将第一个眼睛的片选引脚拉高
if (NUM_EYES > 1) digitalWrite(eye.tft_cs, HIGH); // 如果有第二个眼睛,则将其片选引脚也拉高

// 遍历每个眼睛
for (uint8_t e = 0; e < NUM_EYES; e++) {
    digitalWrite(eye.tft_cs, LOW);   // 将当前眼睛的片选引脚拉低,选中该显示屏
    tft.setRotation(eyeInfo.rotation); // 设置当前显示屏的旋转角度,该角度从 eyeInfo 数组中获取
    tft.fillScreen(TFT_BLACK);          // 使用黑色填充当前显示屏
    digitalWrite(eye.tft_cs, HIGH);    // 将当前眼睛的片选引脚拉高,取消选中该显示屏
}

#if defined(DISPLAY_BACKLIGHT) && (DISPLAY_BACKLIGHT >= 0)
Serial.println("Backlight now on!"); // 通过串口打印 "Backlight now on!"
analogWrite(DISPLAY_BACKLIGHT, BACKLIGHT_MAX); // 使用模拟写入设置背光亮度为最大值
#endif

startTime = millis(); // 记录程序启动时的毫秒数,用于后续的帧率计算
}

// 主循环 -- 在 setup() 函数执行完毕后持续运行 ----------------------------
void loop() {
updateEye(); // 调用 updateEye() 函数来更新眼睛的显示。这个函数应该在其他地方定义 (例如在 eye_functions.cpp 中)。
}

驴友花雕 发表于 2025-5-3 19:27:57

【花雕学编程】Arduino动手做(249)---GC9A01卡通猫眼动画

代码解读:
这段代码是 "UncannyEyes" 项目的一个版本,它使用 ESP32 或其他兼容的微控制器来驱动 TFT LCD 屏幕,模拟逼真的眼睛动画。以下是代码的简单解读:

1、核心功能:
• 模拟眼睛: 代码旨在在 TFT 屏幕上绘制和动画显示一只或两只眼睛。
• 可配置: 眼睛的外观、显示器的配置(数量、连接引脚、旋转方向、位置偏移)等都通过 config.h 文件进行设置。
• 性能优化: 提到了使用 DMA (直接内存访问) 来提高 SPI 通信速度,从而提升动画的帧率 (FPS)。
• 眨眼控制: 支持自动眨眼 (AUTOBLINK),也可以通过按钮手动控制眨眼 (BLINK_PIN, LH_WINK_PIN, RH_WINK_PIN)。
• 输入控制 (可选): 注释部分提到了可以使用模拟摇杆 (JOYSTICK_X_PIN, JOYSTICK_Y_PIN) 或光线传感器 (LIGHT_PIN) 来控制眼睛的运动和瞳孔大小。
• 眼睑追踪 (可选): 如果定义了 TRACKING,眼睑的运动会跟随瞳孔的运动。

2、主要组成部分:
• #include: 引入了必要的库,包括 SPI 通信库和 TFT_eSPI 库,后者是专门为 ESP32 等芯片优化的 TFT LCD 控制库。
• BUFFER_SIZE 和 pbuffer: 定义了一个像素缓冲区,用于在绘制眼睛图像时临时存储像素数据,提高效率。
• eyeInfo_t 结构体: 用于存储每个眼睛的配置信息,包括连接的 TFT 的片选引脚、眨眼按钮引脚、屏幕旋转角度和在屏幕上的 X 轴位置。这些信息从 config.h 文件加载。
• eyeBlink 结构体: 用于管理眼睛的眨眼状态,包括当前状态 (正在闭合、张开、不眨眼)、眨眼持续时间和上次状态改变的时间。
• eye 数组: 存储了 eyeInfo_t 和 eyeBlink 结构体的实例,每个元素对应一只眼睛。
• setup() 函数: 在程序启动时运行一次,用于初始化串口、背光、用户自定义功能 (user_setup())、眼睛 (initEyes()) 和 TFT 显示屏 (tft.init())。它还会根据 config.h 中的设置配置每个眼睛连接的 TFT 屏幕的旋转和初始显示。
• loop() 函数: 在 setup() 之后持续运行,主要调用 updateEye() 函数来更新眼睛的动画。这个 updateEye() 函数的实际实现应该在其他地方 (例如 eye_functions.cpp)。

简单来说,这段代码是一个框架,用于在连接到 ESP32 或类似控制器的 TFT LCD 屏幕上创建生动的眼睛动画。它的核心是通过配置信息和状态管理,控制屏幕上像素的颜色变化,从而模拟眼睛的运动、眨眼等行为。具体的眼睛外观、动画逻辑和控制方式在 config.h 和其他源文件中实现。



驴友花雕 发表于 2025-5-3 19:32:51

【花雕学编程】Arduino动手做(249)---GC9A01卡通猫眼动画

实验场景图动态图




驴友花雕 发表于 2025-5-3 19:34:33

【花雕学编程】Arduino动手做(249)---GC9A01卡通猫眼动画


页: [1]
查看完整版本: 【花雕学编程】Arduino动手做(249)--GC9A01动画发射导弹