76浏览
查看: 76|回复: 9

[项目] 【花雕学编程】Arduino动手做(249)--GC9A01人类淡褐色眼睛

[复制链接]
【花雕学编程】Arduino动手做(249)--GC9A01人类淡褐色眼睛图2

【花雕学编程】Arduino动手做(249)--GC9A01人类淡褐色眼睛图1

驴友花雕  中级技神
 楼主|

发表于 3 天前

【花雕学编程】Arduino动手做(249)--GC9A01人类淡褐色眼睛

【花雕学编程】Arduino动手做(249)--GC9A01人类淡褐色眼睛图1

【花雕学编程】Arduino动手做(249)--GC9A01人类淡褐色眼睛图2
回复

使用道具 举报

驴友花雕  中级技神
 楼主|

发表于 3 天前

【花雕学编程】Arduino动手做(249)--GC9A01人类淡褐色眼睛

【花雕学编程】Arduino动手做(249)--GC9A01人类淡褐色眼睛图1

【花雕学编程】Arduino动手做(249)--GC9A01人类淡褐色眼睛图2
回复

使用道具 举报

驴友花雕  中级技神
 楼主|

发表于 3 天前

【花雕学编程】Arduino动手做(249)--GC9A01人类淡褐色眼睛

【Arduino】189种传感器模块系列实验(资料代码+仿真编程+图形编程)
  实验二百四十九:1.28寸圆形彩色TFT显示屏 高清IPS 模块 240*240 SPI接口GC9A01驱动
  项目之一百二十:ESP32+GC9A01之标准的人类般的淡褐色眼睛

实验开源代码

  1. /*
  2.   【Arduino】189种传感器模块系列实验(资料代码+仿真编程+图形编程)
  3.   实验二百四十九:1.28寸圆形彩色TFT显示屏 高清IPS 模块 240*240 SPI接口GC9A01驱动
  4.   项目之一百二十:ESP32+GC9A01之标准的人类般的淡褐色眼睛
  5. */
  6. //       GC9A01---------- ESP32
  7. //       RST ------------ NC(复位引脚,此处未连接)
  8. //       CS ------------- D4(片选引脚,连接到ESP32的D4引脚)
  9. //       DC ------------- D2(数据/命令选择引脚,连接到ESP32的D2引脚)
  10. //       SDA ------------ D23 (green)(主数据输出引脚,连接到ESP32的D23引脚,绿色线)
  11. //       SCL ------------ D18 (yellow)(时钟信号引脚,连接到ESP32的D18引脚,黄色线)
  12. //       GND ------------ GND(接地引脚,连接到ESP32的接地端)
  13. //       VCC -------------3V3(电源引脚,连接到ESP32的3.3V电源)
  14. // 显示的眼睛的大小取决于屏幕的尺寸和分辨率。
  15. // 眼睛图像的宽度固定为 128 像素。在人类的生理结构中,
  16. // 睑裂 (睁开的眼睛的宽度) 大约是 30 毫米。因此,
  17. // 低分辨率、大像素尺寸的显示屏最适合以真实的比例
  18. // 显示眼睛的图像。请注意,显示器制造商通常会标注对角线尺寸,
  19. // 因此一个 128x128 的 1.7 英寸显示屏或 128x160 的 2 英寸显示屏
  20. // 在尺寸上是比较合适的。
  21. // 眼睛的配置设置,包括眼睛的样式、显示器的数量、
  22. // 片选引脚以及眼睛在屏幕上的 X 轴偏移量,都可以在草图的
  23. // "config.h" 选项卡中进行定义。
  24. // 通过在 ESP32 和 STM32 处理器上使用 DMA (直接内存访问,仅适用于 SPI 显示屏),
  25. // 可以显著提高程序的性能 (以每秒传输的帧数,即 fps 来衡量)。
  26. // 应该使用显示器所支持的尽可能高的 SPI 时钟速率。
  27. // 最小推荐速率为 27MHz,一些显示器甚至可以在 40-80MHz 的更高频率下稳定运行。
  28. // 下表列出了在不同处理器上,使用单只默认眼睛 (defaultEye) 时的性能表现:
  29. //                                 无 DMA    有 DMA
  30. // ESP8266 (160MHz CPU) 40MHz SPI   36 fps
  31. // ESP32 27MHz SPI                 53 fps     85 fps
  32. // ESP32 40MHz SPI                 67 fps    102 fps
  33. // ESP32 80MHz SPI                 82 fps    116 fps // 注意:很少有显示器能在 80MHz 下稳定工作
  34. // STM32F401 55MHz SPI               44 fps     90 fps
  35. // STM32F446 55MHz SPI               83 fps    155 fps
  36. // STM32F767 55MHz SPI              136 fps    197 fps
  37. // 当接口是 SPI 时,DMA 可以与 RP2040、STM32 和 ESP32 处理器一起使用。
  38. // 要启用 DMA,请取消注释下一行:
  39. //#define USE_DMA
  40. // 加载 TFT_eSPI 库,用于控制 TFT LCD
  41. #include <SPI.h>      // 包含 Arduino 的 SPI 库
  42. #include <TFT_eSPI.h> // 包含 TFT_eSPI 库
  43. TFT_eSPI tft;         // 创建一个 TFT_eSPI 类的实例,用于控制显示屏
  44. // 在眼睛的渲染过程中,会使用一个像素缓冲区来存储即将绘制的数据。
  45. // BUFFER_SIZE 定义了这个缓冲区的大小,128 到 1024 似乎是一个最佳的范围。
  46. #define BUFFER_SIZE 240
  47. #ifdef USE_DMA
  48.   #define BUFFERS 2     // 如果启用了 DMA,则使用 2 个缓冲区进行乒乓操作,提高效率
  49. #else
  50.   #define BUFFERS 1     // 如果没有启用 DMA,则只需要 1 个缓冲区
  51. #endif
  52. uint16_t pbuffer[BUFFERS][BUFFER_SIZE]; // 声明一个二维数组作为像素渲染缓冲区,每个缓冲区可以存储 BUFFER_SIZE 个 16 位颜色值
  53. bool      dmaBuf   = 0;                  // 一个布尔变量,用于选择当前正在使用的 DMA 缓冲区 (在双缓冲情况下)
  54. // 这个结构体 (struct) 在 config.h 文件中被填充数据。
  55. typedef struct {                 // 定义一个名为 eyeInfo_t 的结构体,用于存储每个眼睛的配置信息
  56.   int8_t  select;               // 用于连接到每个眼睛的屏幕的片选 (Chip Select, CS) 引脚编号 (int8_t 是 8 位有符号整数)
  57.   int8_t  wink;                 // 连接到每个眼睛的“眨眼”按钮的引脚编号 (int8_t)。如果某个眼睛没有眨眼按钮,则设置为 -1。
  58.   uint8_t rotation;             // 该眼睛所连接的显示屏的旋转角度 (0-3)。uint8_t 是 8 位无符号整数。
  59.   int16_t xposition;            // 眼睛图像在屏幕上的 X 轴位置偏移量 (int16_t 是 16 位有符号整数)。
  60. } eyeInfo_t;
  61. #include "config.h"             // ****** 所有的配置都在这个文件中完成 ******
  62. extern void user_setup(void); // 声明在 user*.cpp 文件中定义的用户自定义初始化函数
  63. extern void user_loop(void);  // 声明在 user*.cpp 文件中定义的用户自定义循环函数
  64. #define SCREEN_X_START 0
  65. #define SCREEN_X_END    SCREEN_WIDTH    // 定义屏幕上眼睛图像的 X 轴范围的起始和结束。SCREEN_WIDTH 应该在 config.h 中定义。
  66. #define SCREEN_Y_START 0
  67. #define SCREEN_Y_END    SCREEN_HEIGHT   // 定义屏幕上眼睛图像的 Y 轴范围的起始和结束。SCREEN_HEIGHT 应该在 config.h 中定义。
  68. // 使用一个简单的状态机来控制眼睛的眨眼 (blink) 和单眼眨眼 (wink) 动作:
  69. #define NOBLINK 0         // 定义一个状态:当前没有进行任何眨眼动作
  70. #define ENBLINK 1         // 定义一个状态:眼睑当前正在闭合 (Engaging Blink)
  71. #define DEBLINK 2         // 定义一个状态:眼睑当前正在张开 (Disengaging Blink)
  72. typedef struct {                 // 定义一个名为 eyeBlink 的结构体,用于存储每个眼睛的眨眼状态信息
  73.   uint8_t  state;         // 当前的眨眼状态 (NOBLINK, ENBLINK, DEBLINK)
  74.   uint32_t duration;      // 当前眨眼状态的持续时间 (以微秒为单位)。uint32_t 是 32 位无符号整数。
  75.   uint32_t startTime;     // 上次眨眼状态发生改变的时间 (以微秒为单位)。
  76. } eyeBlink;
  77. struct {                     // 定义一个匿名结构体,用于存储每个眼睛的特定信息。eye 数组的每个元素都是这个结构体。
  78.   int16_t    tft_cs;         // 连接到每个显示屏的片选 (Chip Select) 引脚编号
  79.   eyeBlink   blink;          // 一个 eyeBlink 结构体,存储该眼睛的当前眨眼状态
  80.   int16_t    xposition;     // 该眼睛的图像在屏幕上的 X 轴位置
  81. } eye[NUM_EYES];              // 声明一个名为 eye 的数组,其大小由 NUM_EYES (在 config.h 中定义) 决定。每个元素存储一只眼睛的信息。
  82. uint32_t startTime;     // 用于记录程序启动或上次帧率计算的时间,以便计算每秒帧数 (FPS)。
  83. // 初始化 -- 在启动时运行一次 --------------------------------------------------
  84. void setup(void) {
  85.   Serial.begin(115200); // 初始化串口通信,波特率为 115200
  86.   //while (!Serial);    // 如果需要等待串口连接,则取消注释此行
  87.   Serial.println("Starting"); // 通过串口打印 "Starting"
  88. #if defined(DISPLAY_BACKLIGHT) && (DISPLAY_BACKLIGHT >= 0)
  89.   // 如果定义了 DISPLAY_BACKLIGHT 并且其值大于等于 0 (表示使用了背光控制引脚)
  90.   Serial.println("Backlight turned off"); // 通过串口打印 "Backlight turned off"
  91.   pinMode(DISPLAY_BACKLIGHT, OUTPUT);  // 将背光控制引脚设置为输出模式
  92.   digitalWrite(DISPLAY_BACKLIGHT, LOW); // 将背光引脚拉低,通常表示关闭背光
  93. #endif
  94.   // 调用用户在 user_setup() 函数中定义的任何附加初始化功能
  95.   user_setup();
  96.   // 初始化眼睛。这个函数可能会设置所有片选引脚为低电平,以便后续的 tft.init() 可以正常工作。
  97.   initEyes(); // 这个函数应该在其他地方定义 (例如在 eye_functions.cpp 中)
  98.   // 初始化 TFT 显示屏
  99.   Serial.println("Initialising displays"); // 通过串口打印 "Initialising displays"
  100.   tft.init();                               // 调用 TFT_eSPI 库的初始化函数
  101. #ifdef USE_DMA
  102.   tft.initDMA(); // 如果定义了 USE_DMA,则初始化 DMA 功能
  103. #endif
  104.   // 拉高片选引脚,以便可以单独配置每个显示屏
  105.   digitalWrite(eye[0].tft_cs, HIGH); // 将第一个眼睛的片选引脚拉高
  106.   if (NUM_EYES > 1) digitalWrite(eye[1].tft_cs, HIGH); // 如果有第二个眼睛,则将其片选引脚也拉高
  107.   // 遍历每个眼睛
  108.   for (uint8_t e = 0; e < NUM_EYES; e++) {
  109.     digitalWrite(eye[e].tft_cs, LOW);     // 将当前眼睛的片选引脚拉低,选中该显示屏
  110.     tft.setRotation(eyeInfo[e].rotation); // 设置当前显示屏的旋转角度,该角度从 eyeInfo 数组中获取
  111.     tft.fillScreen(TFT_BLACK);          // 使用黑色填充当前显示屏
  112.     digitalWrite(eye[e].tft_cs, HIGH);    // 将当前眼睛的片选引脚拉高,取消选中该显示屏
  113.   }
  114. #if defined(DISPLAY_BACKLIGHT) && (DISPLAY_BACKLIGHT >= 0)
  115.   Serial.println("Backlight now on!"); // 通过串口打印 "Backlight now on!"
  116.   analogWrite(DISPLAY_BACKLIGHT, BACKLIGHT_MAX); // 使用模拟写入设置背光亮度为最大值
  117. #endif
  118.   startTime = millis(); // 记录程序启动时的毫秒数,用于后续的帧率计算
  119. }
  120. // 主循环 -- 在 setup() 函数执行完毕后持续运行 ----------------------------
  121. void loop() {
  122.   updateEye(); // 调用 updateEye() 函数来更新眼睛的显示。这个函数应该在其他地方定义 (例如在 eye_functions.cpp 中)。
  123. }
复制代码


回复

使用道具 举报

驴友花雕  中级技神
 楼主|

发表于 3 天前

【花雕学编程】Arduino动手做(249)--GC9A01人类淡褐色眼睛

为了方便起见,这里提供了一个配置文件,如果您添加了纵杆和按钮,则需要编辑此文件。

config.h 文件

  1. // 此处引脚选择基于 Adafruit Learning System 针对 Teensy 3.x 项目的原始指南。
  2. // 其中一些引脚编号甚至在较小的 SAMD M0 和 M4 板上不存在,
  3. // 因此您可能需要进行其他的引脚选择:
  4. // 图形设置 (眼睛外观) ----------------------------------------------------
  5. // 如果使用单眼,您可能希望启用下一行,它使用一个更简单的
  6. // “橄榄球形”眼睛,左右对称。默认形状包含眼睑内侧的小肉阜,
  7. // 创建了明显的左右眼。
  8. //#define SYMMETRICAL_EYELID
  9. // 启用以下 #include 中的一个 -- 包含各种眼睛的大型图形表:
  10. #include "data/defaultEye.h"      // 标准的人类般的淡褐色眼睛 -或-
  11. //#include "data/dragonEye.h"     // 狭缝瞳孔的火龙/恶魔之眼 -或-
  12. //#include "data/noScleraEye.h"   // 大虹膜,无巩膜 -或-
  13. //#include "data/goatEye.h"       // 水平瞳孔的山羊/克朗普斯之眼 -或-
  14. //#include "data/newtEye.h"       // 蝾螈之眼 -或-
  15. //#include "data/terminatorEye.h" // 终结者之眼!
  16. //#include "data/catEye.h"        // 卡通猫眼 (扁平的“2D”颜色)
  17. //#include "data/owlEye.h"        // 猫头鹰之眼 (禁用追踪)
  18. //#include "data/naugaEye.h"      // 瑙加玩偶的咕噜噜眼 (禁用追踪)
  19. //#include "data/doeEye.h"        // 卡通小鹿眼 (禁用追踪)
  20. // 显示硬件设置 (屏幕类型和连接) ----------------------------------------
  21. #define TFT_COUNT 1        // 屏幕数量 (1 或 2)
  22. #define TFT1_CS -1         // TFT 1 片选引脚 (设置为 -1 以使用 TFT_eSPI 设置)
  23. #define TFT2_CS -1         // TFT 2 片选引脚 (设置为 -1 以使用 TFT_eSPI 设置)
  24. #define TFT_1_ROT 1        // TFT 1 旋转角度
  25. #define TFT_2_ROT 1        // TFT 2 旋转角度
  26. #define EYE_1_XPOSITION  60         // 眼睛 1 图像在显示屏上的 X 轴偏移
  27. //#define EYE_2_XPOSITION  320 - 128 // 眼睛 2 图像在显示屏上的 X 轴偏移
  28. #define DISPLAY_BACKLIGHT  -1 // 背光控制引脚 (-1 表示无背光控制)
  29. #define BACKLIGHT_MAX    255
  30. // 眼睛列表 ----------------------------------------------------------------
  31. #define NUM_EYES 1 // 要显示的眼睛数量 (1 或 2)
  32. #define BLINK_PIN   -1 // 手动眨眼按钮引脚 (双眼)
  33. #define LH_WINK_PIN -1 // 左眼眨眼引脚 (设置为 -1 表示无引脚)
  34. #define RH_WINK_PIN -1 // 右眼眨眼引脚 (设置为 -1 表示无引脚)
  35. // 此表包含每只眼睛一行。该表必须存在且名称必须为此名称,
  36. // 并且包含一行或多行。每行包含三个项目:
  37. // 对应 TFT/OLED 显示屏的片选线引脚编号,该眼睛的“眨眼”按钮
  38. // 引脚编号 (如果未使用则为 -1),屏幕旋转值 (0-3) 和该眼睛的 X 轴位置偏移。
  39. #if (NUM_EYES == 2)
  40. eyeInfo_t eyeInfo[] = {
  41.   { TFT1_CS, LH_WINK_PIN, TFT_1_ROT, EYE_1_XPOSITION }, // 左眼片选和眨眼引脚,旋转角度和偏移
  42.   { TFT2_CS, RH_WINK_PIN, TFT_2_ROT, EYE_2_XPOSITION }, // 右眼片选和眨眼引脚,旋转角度和偏移
  43. };
  44. #else
  45. eyeInfo_t eyeInfo[] = {
  46.   { TFT1_CS, LH_WINK_PIN, TFT_1_ROT, EYE_1_XPOSITION }, // 眼睛片选和眨眼引脚,旋转角度和偏移
  47. };
  48. #endif
  49. // 输入设置 (用于控制眼睛运动) --------------------------------------------
  50. // JOYSTICK_X_PIN 和 JOYSTICK_Y_PIN 指定用于手动控制眼睛的模拟摇杆的
  51. // 模拟输入引脚。如果设置为 -1 或未定义,眼睛将自动移动。
  52. // IRIS_PIN 指定用于光敏电阻以使瞳孔对光线做出反应 (或用于手动控制的电位器) 的
  53. // 模拟输入引脚。如果设置为 -1 或未定义,瞳孔将自动变化。
  54. // BLINK_PIN 指定用于按钮 (接地) 的输入引脚,该按钮将使任何/所有眼睛眨眼。
  55. // 如果设置为 -1 或未定义,眼睛仅在定义了 AUTOBLINK 时眨眼,
  56. // 或者如果上面的 eyeInfo[] 表包含每只眼睛的眨眼按钮设置。
  57. //#define JOYSTICK_X_PIN A0 // 眼睛水平位置的模拟引脚 (否则自动)
  58. //#define JOYSTICK_Y_PIN A1 // 眼睛垂直位置的模拟引脚 (同上)
  59. //#define JOYSTICK_X_FLIP   // 如果定义,则反转摇杆 X 轴
  60. //#define JOYSTICK_Y_FLIP   // 如果定义,则反转摇杆 Y 轴
  61. #define TRACKING            // 如果定义,则眼睑追踪瞳孔
  62. #define AUTOBLINK           // 如果定义,眼睛也会自主眨眼
  63. //#define LIGHT_PIN      -1 // 光线传感器引脚
  64. //#define LIGHT_CURVE  0.33 // 光线传感器调整曲线
  65. //#define LIGHT_MIN       0 // 光线传感器的最小有用读数
  66. //#define LIGHT_MAX    1023 // 传感器的最大有用读数
  67. //#define IRIS_SMOOTH         // 如果启用,则过滤来自 IRIS_PIN 的输入
  68. #if !defined(IRIS_MIN)      // 每只眼睛可能有自己的 MIN/MAX
  69. #define IRIS_MIN       90 // 最亮光线下虹膜大小 (0-1023)
  70. #endif
  71. #if !defined(IRIS_MAX)
  72. #define IRIS_MAX      130 // 最暗光线下虹膜大小 (0-1023)
  73. #endif
复制代码


回复

使用道具 举报

驴友花雕  中级技神
 楼主|

发表于 3 天前

【花雕学编程】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 和其他源文件中实现。

回复

使用道具 举报

驴友花雕  中级技神
 楼主|

发表于 3 天前

【花雕学编程】Arduino动手做(249)--GC9A01人类淡褐色眼睛

实验场景图  动态图

【花雕学编程】Arduino动手做(249)--GC9A01人类淡褐色眼睛图1

【花雕学编程】Arduino动手做(249)--GC9A01人类淡褐色眼睛图2
回复

使用道具 举报

驴友花雕  中级技神
 楼主|

发表于 3 天前

【花雕学编程】Arduino动手做(249)--GC9A01人类淡褐色眼睛

【花雕学编程】Arduino动手做(249)--GC9A01人类淡褐色眼睛图1

【花雕学编程】Arduino动手做(249)--GC9A01人类淡褐色眼睛图2
回复

使用道具 举报

驴友花雕  中级技神
 楼主|

发表于 前天 08:27

【花雕学编程】Arduino动手做(249)--GC9A01人类淡褐色眼睛

实验记录视频(33秒)

【【花雕学编程】Arduino动手做(249)---ESP32+GC9A01之标准的人类般的淡褐色眼睛#电子爱好者 #单片机开发 #科技改变生活】

https://www.bilibili.com/video/BV18jLszkE4p/?share_source=copy_web&vd_source=371a292a55e5ca9be994cbb4a86cc987





回复

使用道具 举报

驴友花雕  中级技神
 楼主|

发表于 前天 08:34

【花雕学编程】Arduino动手做(249)--GC9A01人类淡褐色眼睛

实验场景图  动态图

【花雕学编程】Arduino动手做(249)--GC9A01人类淡褐色眼睛图1
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

为本项目制作心愿单
购买心愿单
心愿单 编辑
[[wsData.name]]

硬件清单

  • [[d.name]]
btnicon
我也要做!
点击进入购买页面
上海智位机器人股份有限公司 沪ICP备09038501号-4 备案 沪公网安备31011502402448

© 2013-2025 Comsenz Inc. Powered by Discuz! X3.4 Licensed

mail