一、硬件接线
我选择的是最常见的一块板子: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}; // zconst 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 -1Adafruit_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}; // zconst 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}; // endfloat 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);
}