62浏览
查看: 62|回复: 7

[项目] 【花雕学编程】Arduino动手做(249)---GC9A01独立三立方体

[复制链接]
【花雕学编程】Arduino动手做(249)---GC9A01独立三立方体图2

【花雕学编程】Arduino动手做(249)---GC9A01独立三立方体图1

驴友花雕  中级技神
 楼主|

发表于 2025-4-11 14:10:50

【花雕学编程】Arduino动手做(249)---GC9A01独立三立方体

【花雕学编程】Arduino动手做(249)---GC9A01独立三立方体图1

【花雕学编程】Arduino动手做(249)---GC9A01独立三立方体图2
回复

使用道具 举报

驴友花雕  中级技神
 楼主|

发表于 2025-4-11 14:13:23

【花雕学编程】Arduino动手做(249)---GC9A01独立三立方体

【花雕学编程】Arduino动手做(249)---GC9A01独立三立方体图1

【花雕学编程】Arduino动手做(249)---GC9A01独立三立方体图2
回复

使用道具 举报

驴友花雕  中级技神
 楼主|

发表于 2025-4-11 14:20:47

【花雕学编程】Arduino动手做(249)---GC9A01独立三立方体

  【Arduino】189种传感器模块系列实验(资料代码+仿真编程+图形编程)
  实验二百四十九:1.28寸圆形彩色TFT显示屏 高清IPS 模块 240*240 SPI接口GC9A01驱动
  项目之六十二:GC9A01园屏之3个独立旋转的立方体倾斜 20°位置随机

实验开源代码

  1. /*
  2.   【Arduino】189种传感器模块系列实验(资料代码+仿真编程+图形编程)
  3.   实验二百四十九:1.28寸圆形彩色TFT显示屏 高清IPS 模块 240*240 SPI接口GC9A01驱动
  4.   项目之六十二:GC9A01园屏之3个独立旋转的立方体倾斜 20°位置随机
  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. #include "SPI.h"                      // **包含 SPI 库,用于 TFT 屏幕通信**
  15. #include "Adafruit_GFX.h"             // **包含 Adafruit GFX 图形库,用于绘制图形**
  16. #include "Adafruit_GC9A01A.h"         // **包含 GC9A01A 屏幕驱动库**
  17. #define TFT_CS 4                      // **定义 TFT 屏幕片选引脚**
  18. #define TFT_DC 2                      // **定义 TFT 屏幕数据/命令选择引脚**
  19. #define TFT_RST -1                    // **屏幕复位引脚(-1 表示未使用)**
  20. Adafruit_GC9A01A tft = Adafruit_GC9A01A(TFT_CS, TFT_DC, TFT_RST); // **创建 TFT 屏幕对象**
  21. #define SCREEN_WIDTH 240               // **屏幕宽度**
  22. #define SCREEN_HEIGHT 240              // **屏幕高度**
  23. #define CUBE_SIZE 30                   // **立方体的大小**
  24. #define ROTATION_SPEED 0.05            // **立方体旋转速度**
  25. #define TILT_ANGLE 20 * M_PI / 180     // **定义倾斜角度(20°转换为弧度)**
  26. float angles[3] = {0, 0, 0};           // **3 个立方体的旋转角度**
  27. int cubeX[3];                          // **3 个立方体的 X 坐标**
  28. int cubeY[3];                          // **3 个立方体的 Y 坐标**
  29. uint16_t colors[3] = {
  30.   tft.color565(255, 0, 0),  // **红色**
  31.   tft.color565(0, 0, 255),  // **蓝色**
  32.   tft.color565(0, 255, 0)   // **绿色**
  33. };
  34. // **定义立方体的 3D 顶点坐标**
  35. float cubeVertices[8][3] = {
  36.   { -CUBE_SIZE, -CUBE_SIZE, -CUBE_SIZE},
  37.   { CUBE_SIZE, -CUBE_SIZE, -CUBE_SIZE},
  38.   { CUBE_SIZE,  CUBE_SIZE, -CUBE_SIZE},
  39.   { -CUBE_SIZE,  CUBE_SIZE, -CUBE_SIZE},
  40.   { -CUBE_SIZE, -CUBE_SIZE,  CUBE_SIZE},
  41.   { CUBE_SIZE, -CUBE_SIZE,  CUBE_SIZE},
  42.   { CUBE_SIZE,  CUBE_SIZE,  CUBE_SIZE},
  43.   { -CUBE_SIZE,  CUBE_SIZE,  CUBE_SIZE}
  44. };
  45. // **绘制立方体的边**
  46. void drawEdge(int i, int j, float transformedVertices[8][2], uint16_t color) {
  47.   tft.drawLine(transformedVertices[i][0], transformedVertices[i][1],
  48.                transformedVertices[j][0], transformedVertices[j][1], color);
  49. }
  50. void setup() {
  51.   Serial.begin(115200);               // **初始化串口,方便调试**
  52.   tft.begin();                        // **初始化 TFT 屏幕**
  53.   tft.setRotation(1);                 // **设置屏幕方向**
  54.   tft.fillScreen(tft.color565(0, 0, 0));  // **设置黑色背景**
  55.   // **随机生成 3 个立方体的位置**
  56.   for (int i = 0; i < 3; i++) {
  57.     cubeX[i] = random(40, SCREEN_WIDTH - 40);  // **X 位置随机**
  58.     cubeY[i] = random(40, SCREEN_HEIGHT - 40); // **Y 位置随机**
  59.   }
  60. }
  61. void loop() {
  62.   tft.fillScreen(tft.color565(0, 0, 0)); // **清屏,避免重影**
  63.   // **循环绘制 3 个立方体**
  64.   for (int c = 0; c < 3; c++) {
  65.     float transformedVertices[8][2]; // **存储立方体的 2D 投影坐标**
  66.     for (int i = 0; i < 8; i++) {
  67.       float x = cubeVertices[i][0];  // **获取 X 坐标**
  68.       float y = cubeVertices[i][1];  // **获取 Y 坐标**
  69.       float z = cubeVertices[i][2];  // **获取 Z 坐标**
  70.       // **绕 X 轴倾斜 20°**
  71.       float tiltedY = y * cos(TILT_ANGLE) - z * sin(TILT_ANGLE);
  72.       float tiltedZ = y * sin(TILT_ANGLE) + z * cos(TILT_ANGLE);
  73.       // **绕 Y 轴旋转**
  74.       float rotatedX = x * cos(angles[c]) - tiltedZ * sin(angles[c]);
  75.       float rotatedZ = x * sin(angles[c]) + tiltedZ * cos(angles[c]);
  76.       // **投影到 2D 屏幕**
  77.       transformedVertices[i][0] = cubeX[c] + rotatedX;
  78.       transformedVertices[i][1] = cubeY[c] + tiltedY;
  79.     }
  80.     // **绘制立方体的 12 条边**
  81.     int edges[12][2] = {
  82.       {0, 1}, {1, 2}, {2, 3}, {3, 0},  // **前面四条边**
  83.       {4, 5}, {5, 6}, {6, 7}, {7, 4},  // **背面四条边**
  84.       {0, 4}, {1, 5}, {2, 6}, {3, 7}   // **连接前后面的四条边**
  85.     };
  86.     for (int i = 0; i < 12; i++) {
  87.       drawEdge(edges[i][0], edges[i][1], transformedVertices, colors[c]); // **绘制边线**
  88.     }
  89.     angles[c] += ROTATION_SPEED;  // **更新旋转角度**
  90.   }
  91.   delay(50); // **延迟以控制动画速度**
  92. }
复制代码


回复

使用道具 举报

驴友花雕  中级技神
 楼主|

发表于 2025-4-11 14:23:33

【花雕学编程】Arduino动手做(249)---GC9A01独立三立方体

代码解读:

1. 注释与硬件连接说明

  1. /*
  2.   【Arduino】189种传感器模块系列实验(资料代码+仿真编程+图形编程)
  3.   实验二百四十九:1.28寸圆形彩色TFT显示屏 高清IPS 模块 240*240 SPI接口GC9A01驱动
  4.   项目之六十二:GC9A01园屏之3个独立旋转的立方体倾斜 20°位置随机
  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电源)
复制代码


这部分内容主要是代码的注释和硬件连接说明,告知开发者该代码的实验背景、项目名称以及 GC9A01 显示屏与 ESP32 开发板之间的引脚连接关系。

2. 头文件包含

  1. #include "SPI.h"                      // **包含 SPI 库,用于 TFT 屏幕通信**
  2. #include "Adafruit_GFX.h"             // **包含 Adafruit GFX 图形库,用于绘制图形**
  3. #include "Adafruit_GC9A01A.h"         // **包含 GC9A01A 屏幕驱动库**
复制代码


SPI.h:引入 SPI(串行外设接口)库,用于与 TFT 屏幕进行通信,实现数据的传输。
Adafruit_GFX.h:Adafruit 的图形库,提供了一系列用于绘制图形的基本函数,如绘制线条、矩形、圆形等。
Adafruit_GC9A01A.h:专门针对 GC9A01A 屏幕的驱动库,用于控制该型号的显示屏。

3. 引脚定义与对象创建

  1. #define TFT_CS 4                      // **定义 TFT 屏幕片选引脚**
  2. #define TFT_DC 2                      // **定义 TFT 屏幕数据/命令选择引脚**
  3. #define TFT_RST -1                    // **屏幕复位引脚(-1 表示未使用)**
  4. Adafruit_GC9A01A tft = Adafruit_GC9A01A(TFT_CS, TFT_DC, TFT_RST); // **创建 TFT 屏幕对象**
复制代码


TFT_CS、TFT_DC、TFT_RST:分别定义了 TFT 屏幕的片选引脚、数据 / 命令选择引脚和复位引脚。TFT_RST 为 -1 表示不使用复位引脚。
Adafruit_GC9A01A tft:创建了一个 Adafruit_GC9A01A 类的对象 tft,用于控制 TFT 屏幕。

4. 常量与变量定义

  1. #define SCREEN_WIDTH 240               // **屏幕宽度**
  2. #define SCREEN_HEIGHT 240              // **屏幕高度**
  3. #define CUBE_SIZE 30                   // **立方体的大小**
  4. #define ROTATION_SPEED 0.05            // **立方体旋转速度**
  5. #define TILT_ANGLE 20 * M_PI / 180     // **定义倾斜角度(20°转换为弧度)**
  6. float angles[3] = {0, 0, 0};           // **3 个立方体的旋转角度**
  7. int cubeX[3];                          // **3 个立方体的 X 坐标**
  8. int cubeY[3];                          // **3 个立方体的 Y 坐标**
  9. uint16_t colors[3] = {
  10.   tft.color565(255, 0, 0),  // **红色**
  11.   tft.color565(0, 0, 255),  // **蓝色**
  12.   tft.color565(0, 255, 0)   // **绿色**
  13. };
复制代码

SCREEN_WIDTH 和 SCREEN_HEIGHT:定义了屏幕的宽度和高度,均为 240 像素。
CUBE_SIZE:立方体的大小,即立方体每条边的长度。
ROTATION_SPEED:立方体的旋转速度,控制立方体旋转的快慢。
TILT_ANGLE:将 20° 转换为弧度,用于立方体的倾斜操作。
angles:一个包含 3 个元素的数组,用于存储 3 个立方体的旋转角度,初始值都为 0。
cubeX 和 cubeY:分别存储 3 个立方体的 X 坐标和 Y 坐标。
colors:一个包含 3 个元素的数组,存储 3 个立方体的颜色,分别为红色、蓝色和绿色。

5. 立方体顶点坐标定义

/
  1. / **定义立方体的 3D 顶点坐标**
  2. float cubeVertices[8][3] = {
  3.   { -CUBE_SIZE, -CUBE_SIZE, -CUBE_SIZE},
  4.   { CUBE_SIZE, -CUBE_SIZE, -CUBE_SIZE},
  5.   { CUBE_SIZE,  CUBE_SIZE, -CUBE_SIZE},
  6.   { -CUBE_SIZE,  CUBE_SIZE, -CUBE_SIZE},
  7.   { -CUBE_SIZE, -CUBE_SIZE,  CUBE_SIZE},
  8.   { CUBE_SIZE, -CUBE_SIZE,  CUBE_SIZE},
  9.   { CUBE_SIZE,  CUBE_SIZE,  CUBE_SIZE},
  10.   { -CUBE_SIZE,  CUBE_SIZE,  CUBE_SIZE}
  11. };
复制代码


这是一个二维数组,存储了立方体的 8 个顶点的三维坐标,用于后续的坐标变换和绘制。

6. 绘制立方体边的函数

  1. // **绘制立方体的边**
  2. void drawEdge(int i, int j, float transformedVertices[8][2], uint16_t color) {
  3.   tft.drawLine(transformedVertices[i][0], transformedVertices[i][1],
  4.                transformedVertices[j][0], transformedVertices[j][1], color);
  5. }
复制代码


drawEdge 函数用于绘制立方体的边,接收两个顶点的索引 i 和 j、存储变换后二维坐标的数组 transformedVertices 以及线条颜色 color 作为参数,使用 tft.drawLine 函数在屏幕上绘制一条直线。

7. setup 函数

  1. void setup() {
  2.   Serial.begin(115200);               // **初始化串口,方便调试**
  3.   tft.begin();                        // **初始化 TFT 屏幕**
  4.   tft.setRotation(1);                 // **设置屏幕方向**
  5.   tft.fillScreen(tft.color565(0, 0, 0));  // **设置黑色背景**
  6.   // **随机生成 3 个立方体的位置**
  7.   for (int i = 0; i < 3; i++) {
  8.     cubeX[i] = random(40, SCREEN_WIDTH - 40);  // **X 位置随机**
  9.     cubeY[i] = random(40, SCREEN_HEIGHT - 40); // **Y 位置随机**
  10.   }
  11. }
复制代码

Serial.begin(115200):初始化串口通信,波特率为 115200,方便开发者进行调试信息的输出。
tft.begin():初始化 TFT 屏幕,使其准备好接收和显示数据。
tft.setRotation(1):设置屏幕的旋转方向,这里设置为旋转 1 次(通常是顺时针旋转 90°)。
tft.fillScreen(tft.color565(0, 0, 0)):将屏幕填充为黑色,作为背景颜色。
通过 for 循环随机生成 3 个立方体的 X 坐标和 Y 坐标,范围在距离屏幕边缘 40 像素的内部区域。

8. loop 函数

  1. void loop() {
  2.   tft.fillScreen(tft.color565(0, 0, 0)); // **清屏,避免重影**
  3.   // **循环绘制 3 个立方体**
  4.   for (int c = 0; c < 3; c++) {
  5.     float transformedVertices[8][2]; // **存储立方体的 2D 投影坐标**
  6.     for (int i = 0; i < 8; i++) {
  7.       float x = cubeVertices[i][0];  // **获取 X 坐标**
  8.       float y = cubeVertices[i][1];  // **获取 Y 坐标**
  9.       float z = cubeVertices[i][2];  // **获取 Z 坐标**
  10.       // **绕 X 轴倾斜 20°**
  11.       float tiltedY = y * cos(TILT_ANGLE) - z * sin(TILT_ANGLE);
  12.       float tiltedZ = y * sin(TILT_ANGLE) + z * cos(TILT_ANGLE);
  13.       // **绕 Y 轴旋转**
  14.       float rotatedX = x * cos(angles[c]) - tiltedZ * sin(angles[c]);
  15.       float rotatedZ = x * sin(angles[c]) + tiltedZ * cos(angles[c]);
  16.       // **投影到 2D 屏幕**
  17.       transformedVertices[i][0] = cubeX[c] + rotatedX;
  18.       transformedVertices[i][1] = cubeY[c] + tiltedY;
  19.     }
  20.     // **绘制立方体的 12 条边**
  21.     int edges[12][2] = {
  22.       {0, 1}, {1, 2}, {2, 3}, {3, 0},  // **前面四条边**
  23.       {4, 5}, {5, 6}, {6, 7}, {7, 4},  // **背面四条边**
  24.       {0, 4}, {1, 5}, {2, 6}, {3, 7}   // **连接前后面的四条边**
  25.     };
  26.     for (int i = 0; i < 12; i++) {
  27.       drawEdge(edges[i][0], edges[i][1], transformedVertices, colors[c]); // **绘制边线**
  28.     }
  29.     angles[c] += ROTATION_SPEED;  // **更新旋转角度**
  30.   }
  31.   delay(50); // **延迟以控制动画速度**
  32. }
复制代码

tft.fillScreen(tft.color565(0, 0, 0)):每次循环开始时,将屏幕清屏,避免出现重影现象。
通过外层 for 循环遍历 3 个立方体,对于每个立方体:
定义一个二维数组 transformedVertices 用于存储立方体顶点的二维投影坐标。
内层 for 循环遍历立方体的 8 个顶点,对每个顶点进行坐标变换:
首先绕 X 轴倾斜 20°,通过三角函数计算倾斜后的 Y 和 Z 坐标。
然后绕 Y 轴旋转,计算旋转后的 X 和 Z 坐标。
最后将旋转后的坐标投影到二维屏幕上,加上该立方体的 X 和 Y 坐标,得到最终的二维投影坐标。
定义一个二维数组 edges 存储立方体的 12 条边的顶点索引。
通过另一个 for 循环遍历这 12 条边,调用 drawEdge 函数绘制每条边。
更新该立方体的旋转角度,使其不断旋转。
delay(50):延迟 50 毫秒,控制动画的速度,避免动画过快。

综上所述,这段代码通过不断地对 3 个立方体进行坐标变换和绘制,实现了在 TFT 屏幕上显示 3 个独立旋转且倾斜 20° 的立方体的动画效果,并且立方体的位置是随机生成的。

回复

使用道具 举报

驴友花雕  中级技神
 楼主|

发表于 2025-4-11 14:27:36

【花雕学编程】Arduino动手做(249)---GC9A01独立三立方体

实验场景图  动态图

【花雕学编程】Arduino动手做(249)---GC9A01独立三立方体图2

【花雕学编程】Arduino动手做(249)---GC9A01独立三立方体图1
回复

使用道具 举报

驴友花雕  中级技神
 楼主|

发表于 2025-4-11 14:29:41

【花雕学编程】Arduino动手做(249)---GC9A01独立三立方体

实验场景图  动态图

【花雕学编程】Arduino动手做(249)---GC9A01独立三立方体图1

【花雕学编程】Arduino动手做(249)---GC9A01独立三立方体图2
回复

使用道具 举报

驴友花雕  中级技神
 楼主|

发表于 2025-4-11 14:31:31

【花雕学编程】Arduino动手做(249)---GC9A01独立三立方体

【花雕学编程】Arduino动手做(249)---GC9A01独立三立方体图2

【花雕学编程】Arduino动手做(249)---GC9A01独立三立方体图1
回复

使用道具 举报

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

本版积分规则

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

硬件清单

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

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

mail