【花雕学编程】Arduino动手做(249)---GC9A01独立三立方体
【花雕学编程】Arduino动手做(249)---GC9A01独立三立方体
【花雕学编程】Arduino动手做(249)---GC9A01独立三立方体
【花雕学编程】Arduino动手做(249)---GC9A01独立三立方体
【Arduino】189种传感器模块系列实验(资料代码+仿真编程+图形编程)实验二百四十九:1.28寸圆形彩色TFT显示屏 高清IPS 模块 240*240 SPI接口GC9A01驱动
项目之六十二:GC9A01园屏之3个独立旋转的立方体倾斜 20°位置随机
实验开源代码
/*
【Arduino】189种传感器模块系列实验(资料代码+仿真编程+图形编程)
实验二百四十九:1.28寸圆形彩色TFT显示屏 高清IPS 模块 240*240 SPI接口GC9A01驱动
项目之六十二:GC9A01园屏之3个独立旋转的立方体倾斜 20°位置随机
*/
// 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" // **包含 SPI 库,用于 TFT 屏幕通信**
#include "Adafruit_GFX.h" // **包含 Adafruit GFX 图形库,用于绘制图形**
#include "Adafruit_GC9A01A.h" // **包含 GC9A01A 屏幕驱动库**
#define TFT_CS 4 // **定义 TFT 屏幕片选引脚**
#define TFT_DC 2 // **定义 TFT 屏幕数据/命令选择引脚**
#define TFT_RST -1 // **屏幕复位引脚(-1 表示未使用)**
Adafruit_GC9A01A tft = Adafruit_GC9A01A(TFT_CS, TFT_DC, TFT_RST); // **创建 TFT 屏幕对象**
#define SCREEN_WIDTH 240 // **屏幕宽度**
#define SCREEN_HEIGHT 240 // **屏幕高度**
#define CUBE_SIZE 30 // **立方体的大小**
#define ROTATION_SPEED 0.05 // **立方体旋转速度**
#define TILT_ANGLE 20 * M_PI / 180 // **定义倾斜角度(20°转换为弧度)**
float angles = {0, 0, 0}; // **3 个立方体的旋转角度**
int cubeX; // **3 个立方体的 X 坐标**
int cubeY; // **3 个立方体的 Y 坐标**
uint16_t colors = {
tft.color565(255, 0, 0),// **红色**
tft.color565(0, 0, 255),// **蓝色**
tft.color565(0, 255, 0) // **绿色**
};
// **定义立方体的 3D 顶点坐标**
float cubeVertices = {
{ -CUBE_SIZE, -CUBE_SIZE, -CUBE_SIZE},
{ CUBE_SIZE, -CUBE_SIZE, -CUBE_SIZE},
{ CUBE_SIZE,CUBE_SIZE, -CUBE_SIZE},
{ -CUBE_SIZE,CUBE_SIZE, -CUBE_SIZE},
{ -CUBE_SIZE, -CUBE_SIZE,CUBE_SIZE},
{ CUBE_SIZE, -CUBE_SIZE,CUBE_SIZE},
{ CUBE_SIZE,CUBE_SIZE,CUBE_SIZE},
{ -CUBE_SIZE,CUBE_SIZE,CUBE_SIZE}
};
// **绘制立方体的边**
void drawEdge(int i, int j, float transformedVertices, uint16_t color) {
tft.drawLine(transformedVertices, transformedVertices,
transformedVertices, transformedVertices, color);
}
void setup() {
Serial.begin(115200); // **初始化串口,方便调试**
tft.begin(); // **初始化 TFT 屏幕**
tft.setRotation(1); // **设置屏幕方向**
tft.fillScreen(tft.color565(0, 0, 0));// **设置黑色背景**
// **随机生成 3 个立方体的位置**
for (int i = 0; i < 3; i++) {
cubeX = random(40, SCREEN_WIDTH - 40);// **X 位置随机**
cubeY = random(40, SCREEN_HEIGHT - 40); // **Y 位置随机**
}
}
void loop() {
tft.fillScreen(tft.color565(0, 0, 0)); // **清屏,避免重影**
// **循环绘制 3 个立方体**
for (int c = 0; c < 3; c++) {
float transformedVertices; // **存储立方体的 2D 投影坐标**
for (int i = 0; i < 8; i++) {
float x = cubeVertices;// **获取 X 坐标**
float y = cubeVertices;// **获取 Y 坐标**
float z = cubeVertices;// **获取 Z 坐标**
// **绕 X 轴倾斜 20°**
float tiltedY = y * cos(TILT_ANGLE) - z * sin(TILT_ANGLE);
float tiltedZ = y * sin(TILT_ANGLE) + z * cos(TILT_ANGLE);
// **绕 Y 轴旋转**
float rotatedX = x * cos(angles) - tiltedZ * sin(angles);
float rotatedZ = x * sin(angles) + tiltedZ * cos(angles);
// **投影到 2D 屏幕**
transformedVertices = cubeX + rotatedX;
transformedVertices = cubeY + tiltedY;
}
// **绘制立方体的 12 条边**
int edges = {
{0, 1}, {1, 2}, {2, 3}, {3, 0},// **前面四条边**
{4, 5}, {5, 6}, {6, 7}, {7, 4},// **背面四条边**
{0, 4}, {1, 5}, {2, 6}, {3, 7} // **连接前后面的四条边**
};
for (int i = 0; i < 12; i++) {
drawEdge(edges, edges, transformedVertices, colors); // **绘制边线**
}
angles += ROTATION_SPEED;// **更新旋转角度**
}
delay(50); // **延迟以控制动画速度**
}
【花雕学编程】Arduino动手做(249)---GC9A01独立三立方体
代码解读:1. 注释与硬件连接说明
/*
【Arduino】189种传感器模块系列实验(资料代码+仿真编程+图形编程)
实验二百四十九:1.28寸圆形彩色TFT显示屏 高清IPS 模块 240*240 SPI接口GC9A01驱动
项目之六十二:GC9A01园屏之3个独立旋转的立方体倾斜 20°位置随机
*/
// 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电源)
这部分内容主要是代码的注释和硬件连接说明,告知开发者该代码的实验背景、项目名称以及 GC9A01 显示屏与 ESP32 开发板之间的引脚连接关系。
2. 头文件包含
#include "SPI.h" // **包含 SPI 库,用于 TFT 屏幕通信**
#include "Adafruit_GFX.h" // **包含 Adafruit GFX 图形库,用于绘制图形**
#include "Adafruit_GC9A01A.h" // **包含 GC9A01A 屏幕驱动库**
SPI.h:引入 SPI(串行外设接口)库,用于与 TFT 屏幕进行通信,实现数据的传输。
Adafruit_GFX.h:Adafruit 的图形库,提供了一系列用于绘制图形的基本函数,如绘制线条、矩形、圆形等。
Adafruit_GC9A01A.h:专门针对 GC9A01A 屏幕的驱动库,用于控制该型号的显示屏。
3. 引脚定义与对象创建
#define TFT_CS 4 // **定义 TFT 屏幕片选引脚**
#define TFT_DC 2 // **定义 TFT 屏幕数据/命令选择引脚**
#define TFT_RST -1 // **屏幕复位引脚(-1 表示未使用)**
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. 常量与变量定义
#define SCREEN_WIDTH 240 // **屏幕宽度**
#define SCREEN_HEIGHT 240 // **屏幕高度**
#define CUBE_SIZE 30 // **立方体的大小**
#define ROTATION_SPEED 0.05 // **立方体旋转速度**
#define TILT_ANGLE 20 * M_PI / 180 // **定义倾斜角度(20°转换为弧度)**
float angles = {0, 0, 0}; // **3 个立方体的旋转角度**
int cubeX; // **3 个立方体的 X 坐标**
int cubeY; // **3 个立方体的 Y 坐标**
uint16_t colors = {
tft.color565(255, 0, 0),// **红色**
tft.color565(0, 0, 255),// **蓝色**
tft.color565(0, 255, 0) // **绿色**
};
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. 立方体顶点坐标定义
/
/ **定义立方体的 3D 顶点坐标**
float cubeVertices = {
{ -CUBE_SIZE, -CUBE_SIZE, -CUBE_SIZE},
{ CUBE_SIZE, -CUBE_SIZE, -CUBE_SIZE},
{ CUBE_SIZE,CUBE_SIZE, -CUBE_SIZE},
{ -CUBE_SIZE,CUBE_SIZE, -CUBE_SIZE},
{ -CUBE_SIZE, -CUBE_SIZE,CUBE_SIZE},
{ CUBE_SIZE, -CUBE_SIZE,CUBE_SIZE},
{ CUBE_SIZE,CUBE_SIZE,CUBE_SIZE},
{ -CUBE_SIZE,CUBE_SIZE,CUBE_SIZE}
};
这是一个二维数组,存储了立方体的 8 个顶点的三维坐标,用于后续的坐标变换和绘制。
6. 绘制立方体边的函数
// **绘制立方体的边**
void drawEdge(int i, int j, float transformedVertices, uint16_t color) {
tft.drawLine(transformedVertices, transformedVertices,
transformedVertices, transformedVertices, color);
}
drawEdge 函数用于绘制立方体的边,接收两个顶点的索引 i 和 j、存储变换后二维坐标的数组 transformedVertices 以及线条颜色 color 作为参数,使用 tft.drawLine 函数在屏幕上绘制一条直线。
7. setup 函数
void setup() {
Serial.begin(115200); // **初始化串口,方便调试**
tft.begin(); // **初始化 TFT 屏幕**
tft.setRotation(1); // **设置屏幕方向**
tft.fillScreen(tft.color565(0, 0, 0));// **设置黑色背景**
// **随机生成 3 个立方体的位置**
for (int i = 0; i < 3; i++) {
cubeX = random(40, SCREEN_WIDTH - 40);// **X 位置随机**
cubeY = random(40, SCREEN_HEIGHT - 40); // **Y 位置随机**
}
}
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 函数
void loop() {
tft.fillScreen(tft.color565(0, 0, 0)); // **清屏,避免重影**
// **循环绘制 3 个立方体**
for (int c = 0; c < 3; c++) {
float transformedVertices; // **存储立方体的 2D 投影坐标**
for (int i = 0; i < 8; i++) {
float x = cubeVertices;// **获取 X 坐标**
float y = cubeVertices;// **获取 Y 坐标**
float z = cubeVertices;// **获取 Z 坐标**
// **绕 X 轴倾斜 20°**
float tiltedY = y * cos(TILT_ANGLE) - z * sin(TILT_ANGLE);
float tiltedZ = y * sin(TILT_ANGLE) + z * cos(TILT_ANGLE);
// **绕 Y 轴旋转**
float rotatedX = x * cos(angles) - tiltedZ * sin(angles);
float rotatedZ = x * sin(angles) + tiltedZ * cos(angles);
// **投影到 2D 屏幕**
transformedVertices = cubeX + rotatedX;
transformedVertices = cubeY + tiltedY;
}
// **绘制立方体的 12 条边**
int edges = {
{0, 1}, {1, 2}, {2, 3}, {3, 0},// **前面四条边**
{4, 5}, {5, 6}, {6, 7}, {7, 4},// **背面四条边**
{0, 4}, {1, 5}, {2, 6}, {3, 7} // **连接前后面的四条边**
};
for (int i = 0; i < 12; i++) {
drawEdge(edges, edges, transformedVertices, colors); // **绘制边线**
}
angles += ROTATION_SPEED;// **更新旋转角度**
}
delay(50); // **延迟以控制动画速度**
}
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° 的立方体的动画效果,并且立方体的位置是随机生成的。
【花雕学编程】Arduino动手做(249)---GC9A01独立三立方体
实验场景图动态图【花雕学编程】Arduino动手做(249)---GC9A01独立三立方体
实验场景图动态图【花雕学编程】Arduino动手做(249)---GC9A01独立三立方体
页:
[1]