一、硬件接线
我选择的是最常见的一块板子:ESP-WROOM-32,硬件接线如下:
- 21 - SDA
- 22 - SCL
二、Arduino端代码
我们使用Arduino和Adafruit SSD1306库在OLED显示屏上绘制和旋转一个3D立方体。
首先,定义立方体顶点和边:
`aa`, `bb`, `cc`:定义立方体的8个顶点的x, y, z坐标。
`ff`, `gg`:定义立方体的12条边的起始和终止顶点索引。
const signed int aa[8] = {8, -8, -8, 8, 8, -8, -8, 8}; // x
const signed int bb[8] = {8, 8, -8, -8, 8, 8, -8, -8}; // y
const signed int cc[8] = {-8, -8, -8, -8, 8, 8, 8, 8}; // z
const int ff[12] = {0, 1, 2, 3, 4, 5, 6, 7, 0, 1, 2, 3}; // start
const int gg[12] = {1, 2, 3, 0, 5, 6, 7, 4, 4, 5, 6, 7}; // end
接着,初始化旋转角度:
`rotx`, `roty`, `rotz`:定义绕x轴、y轴和z轴的旋转角度。
float rotx = 0.0;
float roty = 0.0;
float rotz = 0.0;
然后,计算旋转后的立方体顶点,并在OLED屏幕上绘制,定义`Disply3D`函数:计算旋转矩阵(绕x, y, z轴的旋转矩阵),遍历每个顶点,应用旋转矩阵,更新顶点坐标。将每个顶点的3D坐标转换为2D屏幕坐标。清空显示屏并绘制立方体的12条边。
最后,在主函数里不断循环更新立方体的旋转角度,并调用 `Disply3D` 函数进行绘制。
完整代码如下:
#include <Wire.h>
#include <Adafruit_SSD1306.h>
#include <math.h>
#define SCREEN_WIDTH 128
#define SCREEN_HEIGHT 64
#define OLED_RESET -1
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);
const signed int aa[8] = {8, -8, -8, 8, 8, -8, -8, 8}; // x
const signed int bb[8] = {8, 8, -8, -8, 8, 8, -8, -8}; // y
const signed int cc[8] = {-8, -8, -8, -8, 8, 8, 8, 8}; // z
const int ff[12] = {0, 1, 2, 3, 4, 5, 6, 7, 0, 1, 2, 3}; // start
const int gg[12] = {1, 2, 3, 0, 5, 6, 7, 4, 4, 5, 6, 7}; // end
float rotx = 0.0;
float roty = 0.0;
float rotz = 0.0;
void setup() {
Serial.begin(9600);
if(!display.begin(SSD1306_SWITCHCAPVCC, 0x3C)) {
Serial.println(F("SSD1306 allocation failed"));
for(;;);
}
display.clearDisplay();
}
void Disply3D(float xpos, float ypos, float zpos) {
int newx[8];
int newy[8];
float sinax = sin(rotx);
float cosax = cos(rotx);
float sinay = sin(roty);
float cosay = cos(roty);
float sinaz = sin(rotz);
float cosaz = cos(rotz);
for (int i = 0; i < 8; i++)
{
float x = aa[i];
float y = bb[i];
float z = cc[i];
float yt = y * cosax - z * sinax;
float zt = y * sinax + z * cosax;
y = yt;
z = zt;
float xt = x * cosay - z * sinay;
zt = x * sinay + z * cosay;
x = xt;
z = zt;
xt = x * cosaz - y * sinaz;
yt = x * sinaz + y * cosaz;
x = xt;
y = yt;
x = x + xpos;
y = y + ypos;
z = z + zpos;
newx[i] = (x * 64 / z) + SCREEN_WIDTH / 2;
newy[i] = (y * 64 / z) + SCREEN_HEIGHT / 2;
}
display.clearDisplay();
for (int i = 0; i < 12; i++) {
int vertex = ff[i];
int sx = newx[vertex];
int sy = newy[vertex];
vertex = gg[i];
int ex = newx[vertex];
int ey = newy[vertex];
display.drawLine(sx, sy, ex, ey, SSD1306_WHITE);
}
display.display();
}
void loop() {
Disply3D(0, 0, 31);
rotx += 0.02;
roty += 0.03;
rotz += 0.01;
delay(50);
}