【花雕学编程】Arduino动手做(249)--GC9A01屏37个特色案例
代码说明1、双螺线反向旋转:
使用 direction 参数控制螺线旋转方向,一条顺时针旋转,另一条逆时针旋转。
2、随机变色:
每帧为两条螺线随机选择颜色,增强动画的多样性和视觉冲击力。
3、动态极坐标更新:
极坐标公式 $r = a\theta$ 与旋转角度结合,使螺线保持平滑的动态扩展和旋转。
4、流畅动画:
每帧清屏并重新绘制两条螺线,旋转角度每次增加 ROTATION_SPEED,保证动画自然流畅。
5、效果描述
屏幕中央绘制两条动态旋转的阿基米德螺线,一条顺时针旋转,另一条逆时针旋转。
每帧螺线的颜色随机切换,展现五彩斑斓的效果。
整体视觉充满动感,适合作为数学几何或动态艺术的展示。
【花雕学编程】Arduino动手做(249)--GC9A01屏37个特色案例
实验场景图动态图【花雕学编程】Arduino动手做(249)--GC9A01屏37个特色案例
【花雕学编程】Arduino动手做(249)--GC9A01屏38个特色案例
【Arduino】189种传感器模块系列实验(资料代码+仿真编程+图形编程)实验二百四十九:1.28寸圆形彩色TFT显示屏 高清IPS 模块 240*240 SPI接口GC9A01驱动
项目实验之三十八:多彩动态旋转的多条对数螺
实验开源代码
/*
【Arduino】189种传感器模块系列实验(资料代码+仿真编程+图形编程)
实验二百四十九:1.28寸圆形彩色TFT显示屏 高清IPS 模块 240*240 SPI接口GC9A01驱动
项目实验之三十八:多彩动态旋转的多条对数螺
*/
// 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 "Adafruit_GFX.h"
#include "Adafruit_GC9A01A.h"
// 定义屏幕引脚
#define TFT_CS 4 // 片选引脚
#define TFT_DC 2 // 数据/命令引脚
#define TFT_RST -1 // 重置引脚(未使用时设置为 -1)
// 初始化屏幕对象
Adafruit_GC9A01A tft = Adafruit_GC9A01A(TFT_CS, TFT_DC, TFT_RST);
// 定义对数螺线参数
#define CENTER_X 120 // 屏幕中心 X
#define CENTER_Y 120 // 屏幕中心 Y
#define MAX_RADIUS 120 // 最大半径
#define SPIRAL_COUNT 6 // 螺线数量
#define STEP 0.1 // 每次增加的角度步进(弧度)
#define ROTATION_SPEED 3 // 每帧旋转的角度(度)
#define GROWTH_FACTOR 1.1 // 对数螺线增长因子
// 定义颜色数组
uint16_t colors[] = {GC9A01A_RED, GC9A01A_GREEN, GC9A01A_BLUE, GC9A01A_YELLOW, GC9A01A_MAGENTA, GC9A01A_CYAN, GC9A01A_WHITE};
int numColors = sizeof(colors) / sizeof(colors);
// 绘制一条对数螺线
void drawLogarithmicSpiral(float rotationAngle, float phase, uint16_t color) {
float theta = 0;// 初始化角度
int prevX = CENTER_X, prevY = CENTER_Y; // 初始点
while (theta < MAX_RADIUS / GROWTH_FACTOR) {
// 计算极坐标 r 和笛卡尔坐标 (x, y)
float r = GROWTH_FACTOR * exp(0.1 * theta);
float adjustedTheta = theta + rotationAngle * 3.14159 / 180 + phase; // 添加旋转角度和相位偏移
int x = CENTER_X + r * cos(adjustedTheta);
int y = CENTER_Y + r * sin(adjustedTheta);
// 连接当前点和前一个点
tft.drawLine(prevX, prevY, x, y, color);
// 更新前一个点和角度
prevX = x;
prevY = y;
theta += STEP; // 增加角度
}
}
void setup() {
Serial.begin(115200); // 初始化串口通信
Serial.println("Multi Logarithmic Spirals with Dynamic Colors");
tft.begin(); // 初始化屏幕
tft.setRotation(0); // 设置屏幕方向
tft.fillScreen(GC9A01A_BLACK); // 设置黑色背景
}
void loop() {
static float rotationAngle = 0; // 初始化旋转角度
// 清屏
tft.fillScreen(GC9A01A_BLACK);
// 绘制多条螺线
for (int i = 0; i < SPIRAL_COUNT; i++) {
// 随机颜色
uint16_t color = colors;
// 添加相位偏移,使每条螺线有不同起点
float phase = i * (2 * 3.14159 / SPIRAL_COUNT);
// 绘制螺线
drawLogarithmicSpiral(rotationAngle, phase, color);
}
// 更新旋转角度
rotationAngle += ROTATION_SPEED;
if (rotationAngle >= 360) {
rotationAngle = 0; // 重置角度
}
delay(100); // 控制帧速率
}
【花雕学编程】Arduino动手做(249)--GC9A01屏38个特色案例
代码说明1、多螺线动态旋转:
同时绘制 SPIRAL_COUNT 条对数螺线,每条螺线具有不同的相位偏移,形成复杂的几何图案。
2、随机颜色切换:
每帧为螺线随机分配颜色,使动画充满多样性。
3、对数螺线生成:
采用对数公式 $r = a e^{b\theta}$,实现平滑扩展的螺线形状。
4、平滑动画:
旋转角度 rotationAngle 每帧更新,动态变化自然,延迟 100ms 控制帧速率。
5、效果描述
屏幕中央显示多条对数螺线,旋转时螺线的颜色动态变化,视觉效果华丽。
每条螺线的初始角度不同,图案具有对称性和层次感。
动态旋转螺线形成复杂的几何艺术,非常适合圆形屏幕展示。
【花雕学编程】Arduino动手做(249)--GC9A01屏38个特色案例
实验场景图动态图【花雕学编程】Arduino动手做(249)--GC9A01屏38个特色案例
【花雕学编程】Arduino动手做(249)--GC9A01屏38个特色案例
【花雕学编程】Arduino动手做(249)--GC9A01屏39个特色案例
【Arduino】189种传感器模块系列实验(资料代码+仿真编程+图形编程)实验二百四十九:1.28寸圆形彩色TFT显示屏 高清IPS 模块 240*240 SPI接口GC9A01驱动
项目实验之三十九:模拟手表时钟指针、数字时间显示、日期窗口和装饰性刻度
实验开源代码
/*
【Arduino】189种传感器模块系列实验(资料代码+仿真编程+图形编程)
实验二百四十九:1.28寸圆形彩色TFT显示屏 高清IPS 模块 240*240 SPI接口GC9A01驱动
项目实验之三十九:模拟手表时钟指针、数字时间显示、日期窗口和装饰性刻度
*/
// 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 "Adafruit_GFX.h"
#include "Adafruit_GC9A01A.h"
// 定义屏幕引脚
#define TFT_CS 4 // 片选引脚
#define TFT_DC 2 // 数据/命令引脚
#define TFT_RST -1 // 重置引脚(未使用时设置为 -1)
// 初始化屏幕对象
Adafruit_GC9A01A tft = Adafruit_GC9A01A(TFT_CS, TFT_DC, TFT_RST);
// 定义屏幕中心
#define SCREEN_CENTER_X 120
#define SCREEN_CENTER_Y 120
#define CLOCK_RADIUS 100
#define HAND_COLOR GC9A01A_WHITE // 指针颜色
// 初始化时间变量
int hours = 01, minutes = 42, seconds = 00; // 初始化时间为 01:42:00
void drawClockFace() {
// 绘制表盘外圈
tft.drawCircle(SCREEN_CENTER_X, SCREEN_CENTER_Y, CLOCK_RADIUS, GC9A01A_WHITE);
tft.drawCircle(SCREEN_CENTER_X, SCREEN_CENTER_Y, CLOCK_RADIUS - 5, GC9A01A_CYAN);
// 绘制小时刻度
for (int i = 0; i < 12; i++) {
float angle = i * 30 * 3.14159 / 180;
int x1 = SCREEN_CENTER_X + (CLOCK_RADIUS - 10) * cos(angle);
int y1 = SCREEN_CENTER_Y + (CLOCK_RADIUS - 10) * sin(angle);
int x2 = SCREEN_CENTER_X + (CLOCK_RADIUS - 20) * cos(angle);
int y2 = SCREEN_CENTER_Y + (CLOCK_RADIUS - 20) * sin(angle);
tft.drawLine(x1, y1, x2, y2, GC9A01A_WHITE);
}
// 绘制分钟刻度
for (int i = 0; i < 60; i++) {
if (i % 5 != 0) { // 避开小时刻度
float angle = i * 6 * 3.14159 / 180;
int x1 = SCREEN_CENTER_X + (CLOCK_RADIUS - 10) * cos(angle);
int y1 = SCREEN_CENTER_Y + (CLOCK_RADIUS - 10) * sin(angle);
tft.drawPixel(x1, y1, GC9A01A_YELLOW);
}
}
}
void drawHands() {
// 计算时针位置
float hourAngle = (hours % 12 + minutes / 60.0) * 30 * 3.14159 / 180;
int hourX = SCREEN_CENTER_X + (CLOCK_RADIUS - 50) * cos(hourAngle);
int hourY = SCREEN_CENTER_Y + (CLOCK_RADIUS - 50) * sin(hourAngle);
tft.drawLine(SCREEN_CENTER_X, SCREEN_CENTER_Y, hourX, hourY, HAND_COLOR);
// 计算分针位置
float minuteAngle = (minutes + seconds / 60.0) * 6 * 3.14159 / 180;
int minuteX = SCREEN_CENTER_X + (CLOCK_RADIUS - 30) * cos(minuteAngle);
int minuteY = SCREEN_CENTER_Y + (CLOCK_RADIUS - 30) * sin(minuteAngle);
tft.drawLine(SCREEN_CENTER_X, SCREEN_CENTER_Y, minuteX, minuteY, GC9A01A_GREEN);
// 计算秒针位置
float secondAngle = seconds * 6 * 3.14159 / 180;
int secondX = SCREEN_CENTER_X + (CLOCK_RADIUS - 20) * cos(secondAngle);
int secondY = SCREEN_CENTER_Y + (CLOCK_RADIUS - 20) * sin(secondAngle);
tft.drawLine(SCREEN_CENTER_X, SCREEN_CENTER_Y, secondX, secondY, GC9A01A_RED);
}
void displayDigitalTime() {
// 绘制数字时间
tft.setTextSize(2);
tft.setTextColor(GC9A01A_WHITE, GC9A01A_BLACK); // 白色文字,黑色背景
tft.setCursor(73, 160);
tft.printf("%02d:%02d:%02d", hours, minutes, seconds);
// 显示日期窗口
tft.setTextSize(2);
tft.setCursor(62, 180);
tft.printf("2025/03/28");
}
void updateClock() {
seconds++;
if (seconds >= 60) {
seconds = 0;
minutes++;
}
if (minutes >= 60) {
minutes = 0;
hours++;
}
if (hours >= 24) {
hours = 0;
}
}
void setup() {
Serial.begin(115200); // 初始化串口通信
Serial.println("Complex Watch Face");
tft.begin(); // 初始化屏幕
tft.setRotation(2); // 设置屏幕方向
tft.fillScreen(GC9A01A_BLACK);// 清屏设置为黑色背景
drawClockFace(); // 绘制表盘
}
void loop() {
// 清除上一帧的指针和数字区域
tft.fillCircle(SCREEN_CENTER_X, SCREEN_CENTER_Y, CLOCK_RADIUS - 5, GC9A01A_BLACK);
// 更新动态内容
drawClockFace();
drawHands();
displayDigitalTime();
updateClock();
delay(1000); // 每秒刷新一次
}
【花雕学编程】Arduino动手做(249)--GC9A01屏39个特色案例
代码说明1、复杂表盘设计:
多层刻度:包括小时刻度和分钟刻度。
双功能显示:模拟指针显示和数字时间显示同时存在。
2、动态时间更新:
时间每秒更新,分针和时针会根据当前时间调整位置。
3、多色指针:
不同颜色用于区分秒针(红色)、分针(绿色)和时针(白色)。
4、装饰性圆圈:
表盘边缘绘制多层圆圈,增强设计美感。
5、时间和日期显示:
在表盘底部显示当前时间和固定的日期信息。
6、效果描述
表盘中央模拟指针式时钟,刻度和指针分明,色彩丰富。
底部数字显示当前时间和固定日期信息,结合现代和经典设计。
动态更新的时间显示,让表盘实时变化。
【花雕学编程】Arduino动手做(249)--GC9A01屏39个特色案例
代码解读1、屏幕初始化
#include "SPI.h"
#include "Adafruit_GFX.h"
#include "Adafruit_GC9A01A.h"
引入 SPI 和 Adafruit_GFX 库,用于图形绘制功能。
引入 Adafruit_GC9A01A 库,专用于驱动 GC9A01A 圆形屏幕,提供绘制圆形、线条、文字等能力。
2、屏幕硬件配置
#define TFT_CS 4
#define TFT_DC 2
#define TFT_RST -1
Adafruit_GC9A01A tft = Adafruit_GC9A01A(TFT_CS, TFT_DC, TFT_RST);
TFT_CS、TFT_DC 和 TFT_RST 是屏幕的引脚定义。
TFT_RST 为 -1,表示未使用复位引脚。
使用 Adafruit_GC9A01A 初始化屏幕对象 tft。
3、 屏幕中心和表盘参数
#define SCREEN_CENTER_X 120
#define SCREEN_CENTER_Y 120
#define CLOCK_RADIUS 100
#define HAND_COLOR GC9A01A_WHITE
定义屏幕中心 (120, 120),适配 GC9A01A 的圆形屏幕(分辨率 240x240 像素)。
表盘半径设置为 100 像素,指针颜色设为白色。
4、时间变量初始化
int hours = 01, minutes = 42, seconds = 00;
时间初始化为 01:42:00。
5、绘制表盘的功能
5.1 绘制表盘外圈
tft.drawCircle(SCREEN_CENTER_X, SCREEN_CENTER_Y, CLOCK_RADIUS, GC9A01A_WHITE);
tft.drawCircle(SCREEN_CENTER_X, SCREEN_CENTER_Y, CLOCK_RADIUS - 5, GC9A01A_CYAN);
绘制两个同心圆,形成表盘外圈,分别使用白色和青色,增加美感。
5.2 绘制小时刻度
for (int i = 0; i < 12; i++) {
float angle = i * 30 * 3.14159 / 180;
int x1 = SCREEN_CENTER_X + (CLOCK_RADIUS - 10) * cos(angle);
int y1 = SCREEN_CENTER_Y + (CLOCK_RADIUS - 10) * sin(angle);
int x2 = SCREEN_CENTER_X + (CLOCK_RADIUS - 20) * cos(angle);
int y2 = SCREEN_CENTER_Y + (CLOCK_RADIUS - 20) * sin(angle);
tft.drawLine(x1, y1, x2, y2, GC9A01A_WHITE);
}
使用 cos 和 sin 函数计算小时刻度位置(角度每小时增加 30°)。
两点 (x1, y1) 和 (x2, y2) 通过 drawLine 绘制刻度线。
5.3 绘制分钟刻度
for (int i = 0; i < 60; i++) {
if (i % 5 != 0) { // 避开小时刻度
float angle = i * 6 * 3.14159 / 180;
int x1 = SCREEN_CENTER_X + (CLOCK_RADIUS - 10) * cos(angle);
int y1 = SCREEN_CENTER_Y + (CLOCK_RADIUS - 10) * sin(angle);
tft.drawPixel(x1, y1, GC9A01A_YELLOW);
}
}
使用 cos 和 sin 函数计算分钟刻度位置(角度每分钟增加 6°)。
每 5 分钟避开小时刻度,仅绘制点刻度。
6、绘制指针的功能
6.1 时针
float hourAngle = (hours % 12 + minutes / 60.0) * 30 * 3.14159 / 180;
int hourX = SCREEN_CENTER_X + (CLOCK_RADIUS - 50) * cos(hourAngle);
int hourY = SCREEN_CENTER_Y + (CLOCK_RADIUS - 50) * sin(hourAngle);
tft.drawLine(SCREEN_CENTER_X, SCREEN_CENTER_Y, hourX, hourY, HAND_COLOR);
根据当前时间计算时针角度:
每小时角度增量为 30°,并加入分钟的偏移。
时针长度为半径减 50 像素。
6.2 分针
float minuteAngle = (minutes + seconds / 60.0) * 6 * 3.14159 / 180;
int minuteX = SCREEN_CENTER_X + (CLOCK_RADIUS - 30) * cos(minuteAngle);
int minuteY = SCREEN_CENTER_Y + (CLOCK_RADIUS - 30) * sin(minuteAngle);
tft.drawLine(SCREEN_CENTER_X, SCREEN_CENTER_Y, minuteX, minuteY, GC9A01A_GREEN);
分针角度每分钟增加 6°,同时加入秒数偏移。
分针长度为半径减 30 像素。
6.3 秒针
float secondAngle = seconds * 6 * 3.14159 / 180;
int secondX = SCREEN_CENTER_X + (CLOCK_RADIUS - 20) * cos(secondAngle);
int secondY = SCREEN_CENTER_Y + (CLOCK_RADIUS - 20) * sin(secondAngle);
tft.drawLine(SCREEN_CENTER_X, SCREEN_CENTER_Y, secondX, secondY, GC9A01A_RED);
秒针角度每秒增加 6°。
秒针长度为半径减 20 像素。
7、显示数字时间
tft.setTextSize(2);
tft.setTextColor(GC9A01A_WHITE, GC9A01A_BLACK); // 白色文字,黑色背景
tft.setCursor(73, 160);
tft.printf("%02d:%02d:%02d", hours, minutes, seconds);
显示数字时间,格式为 01:42:00,居中显示在表盘下方。
8、更新时间
seconds++;
if (seconds >= 60) {
seconds = 0;
minutes++;
}
if (minutes >= 60) {
minutes = 0;
hours++;
}
if (hours >= 24) {
hours = 0;
}
每秒更新时间变量,并递归处理分钟和小时的变化。
9、主循环
tft.fillCircle(SCREEN_CENTER_X, SCREEN_CENTER_Y, CLOCK_RADIUS - 5, GC9A01A_BLACK);
drawClockFace();
drawHands();
displayDigitalTime();
updateClock();
delay(1000);
清除上一帧内容,绘制表盘、指针和数字时间,并更新时间。
以每秒 (delay(1000)) 的速率刷新表盘内容。