当前位置:首页>Linux>AI 帮我做一个光立方:Linux 环境下从电路设计到单片机编程的完整教程

AI 帮我做一个光立方:Linux 环境下从电路设计到单片机编程的完整教程

  • 2026-09-12 14:54:32
AI 帮我做一个光立方:Linux 环境下从电路设计到单片机编程的完整教程

AI 帮我做一个光立方:Linux 环境下从电路设计到单片机编程的完整教程

零基础上手,用 AI 辅助完成一个炫酷的 3D LED 光立方项目

💡 提示: 本文配套开源项目(含原理图、PCB、源码)已上传 GitHub,文末获取!


📌 前言

光立方是一个经典的电子制作项目,通过 64 颗 LED 组成 4×4×4 的三维阵列,利用视觉暂留原理实现各种炫酷的 3D 动画效果。

传统教程往往只讲硬件或只讲软件,而且大多基于 Windows 环境。今天这篇教程,我将展示如何在 Linux 系统下,借助 AI 大模型的辅助,从零开始完成一个完整的光立方项目。

全程使用免费开源工具,总成本不到 50 元!


🎯 项目目标

  • ✅ 在 Linux 环境下完成电路设计(KiCad)
  • ✅ 用 AI 辅助生成单片机代码(STM32)
  • ✅ 掌握光立方的工作原理
  • ✅ 完成硬件焊接和程序烧录
  • ✅ 实现多种 3D 动画效果

📦 一、材料清单

1.1 核心元件

实物参考:

┌────────────────────────────────────────┐
│  LED ×64   STM32   74HC595   ULN2003  │
│   ●●●●    ┌───┐   ┌────┐   ┌────┐    │
│   ●●●●    │ ● │   │ ●● │   │ ●● │    │
│   ●●●●    └───┘   └────┘   └────┘    │
│   电阻×64  排针若干  PCB 板  5V 电源  │
└────────────────────────────────────────┘
元件 规格 数量 单价 小计
LED 3mm 发光二极管 64 颗 ¥0.1 ¥6.4
单片机 STM32F103C8T6 1 片 ¥15 ¥15
移位寄存器 74HC595 2 片 ¥1 ¥2
驱动芯片 ULN2003 4 片 ¥1 ¥4
电阻 220Ω 1/4W 64 个 ¥0.01 ¥0.6
排针排母 2.54mm 若干 - ¥5
PCB 板 定制或洞洞板 1 块 ¥0 ¥0
电源 5V 1A 1 个 ¥10 ¥10
合计 - - - 约¥43

1.2 采购建议

  • 淘宝/拼多多: 搜索"STM32 最小系统板"、"LED 3mm 混色"
  • 立创商城: 元器件品质好,适合批量采购
  • 嘉立创: PCB 每月 2 次免费打样(10cm²内)

🖥️ 二、Linux 开发环境搭建

2.1 安装 KiCad(电路设计)

# Ubuntu/Debian
sudo apt update
sudo apt install kicad

# Fedora
sudo dnf install kicad

# Arch Linux
sudo pacman -S kicad

KiCad 是一款开源专业的 EDA 工具,支持原理图设计和 PCB 布局,完全免费且功能强大。

2.2 安装 STM32 开发工具链

# 安装 ARM GCC 编译器
sudo apt install gcc-arm-none-eabi gdb-multiarch

# 安装 ST-Link 烧录工具
sudo apt install stlink-tools

# 或安装 OpenOCD
sudo apt install openocd

2.3 安装 VS Code 和 PlatformIO

# 安装 VS Code
sudo snap install code --classic

# 安装 PlatformIO(命令行方式)
sudo apt install python3-pip
pip3 install platformio

# 或在 VS Code 中安装 PlatformIO 插件

PlatformIO 是一个跨平台的嵌入式开发环境,支持 STM32、Arduino、ESP32 等多种平台,自动管理依赖,强烈推荐!


🔌 三、电路设计(KiCad 实战)

3.1 光立方工作原理

逐层扫描示意:

    层 3  ┌─┬─┬─┬─┐   ← 先点亮层 3,显示对应图案
        │●│ │●│ │
        ├─┼─┼─┼─┤
    层 2  │ │●│ │●│   ← 再点亮层 2
        ├─┼─┼─┼─┤
    层 1  │●│ │ │●│   ← 再点亮层 1
        ├─┼─┼─┼─┤
    层 0  │ │●│●│ │   ← 最后点亮层 0
        └─┴─┴─┴─┘
        
    扫描频率 > 100Hz → 人眼看到完整 3D 图像(视觉暂留)

光立方采用逐层扫描的方式显示:

┌─────────────────────────────────┐
│  层选(共阴极):每层 16 个 LED    │
│  阴极连在一起 → 4 个层选信号      │
│                                 │
│  列选(共阳极):每列 4 个 LED     │
│  阳极连在一起 → 16 个列选信号     │
│                                 │
│  控制方式:逐层扫描(视觉暂留)   │
└─────────────────────────────────┘

3.2 创建 KiCad 项目

KiCad 项目结构:

led-cube/
├── led-cube.kicad_pro    # 项目文件
├── led-cube_sch          # 原理图
├── led-cube_pcb          # PCB 布局
└── led-cube.kicad_prl    # 项目设置
mkdir ~/projects/led-cube
cd ~/projects/led-cube
kicad led-cube.kicad_pro

3.3 绘制原理图要点

  1. LED 阵列: 64 颗 LED 按 4×4×4 排列
  2. 限流电阻: 每颗 LED 串联 220Ω 电阻(计算:(5V-2V)/20mA≈150Ω,取 220Ω 更安全)
  3. 层驱动: ULN2003 达林顿管驱动每层阴极
  4. 列驱动: 2 片 74HC595 串转并控制 16 列阳极
  5. 单片机: STM32F103C8T6 最小系统

3.4 关键电路连接

STM32 引脚分配:
├── PA0-PA3: 层选信号(连接 ULN2003)
├── PB3: 74HC595 时钟(SH_CP)
├── PB4: 74HC595 锁存(ST_CP)
└── PB5: 74HC595 数据(DS)

74HC595 级联:
├── 第一片:控制列 0-7
├── 第二片:控制列 8-15
└── Q7' → 下一片 DS(级联)

3.5 PCB 布局建议

  • 底层: STM32 最小系统 + ST-Link 接口
  • 中层: 74HC595 + ULN2003 驱动电路
  • 顶层: LED 阵列插座(方便焊接)
  • 电源: 5V 输入,加 100μF 滤波电容

3.6 输出生产文件

File → Plot → Gerber(发给 PCB 厂家)
File → Fabrication Outputs → BOM(元件清单)

💻 四、单片机编程(AI 辅助)

4.1 创建 PlatformIO 项目

cd ~/projects/led-cube
pio project create --ide vscode --board bluepill_f103c8 --platform ststm32

4.2 项目结构

led-cube/
├── src/
│   └── main.cpp          # 主程序
├── include/
│   └── led_cube.h        # 头文件
├── lib/                   # 第三方库
├── platformio.ini         # 配置文件
└── README.md

4.3 核心代码实现

配置文件(platformio.ini)

[env:bluepill_f103c8]
platform = ststm32
board = bluepill_f103c8
framework = arduino
upload_protocol = stlink
upload_speed = 921600
monitor_speed = 115200

主程序(main.cpp)

#include <Arduino.h>

// ========== 引脚定义 ==========
#define LAYER_PIN_START  PA0   // 层选引脚 PA0-PA3
#define DATA_PIN         PB5   // 74HC595 数据
#define CLOCK_PIN        PB3   // 时钟
#define LATCH_PIN        PB4   // 锁存

// ========== 显存定义 ==========
// 4 层 × 16 列
uint8_t cube[4][16];

// ========== 初始化 ==========
void setup() {
    pinMode(DATA_PIN, OUTPUT);
    pinMode(CLOCK_PIN, OUTPUT);
    pinMode(LATCH_PIN, OUTPUT);
    
    for(int i = 0; i < 4; i++) {
        pinMode(LAYER_PIN_START + i, OUTPUT);
    }
    
    memset(cube, 0, sizeof(cube));
}

// ========== 74HC595 数据发送 ==========
void shiftOutData(uint16_t data) {
    for(int i = 15; i >= 0; i--) {
        digitalWrite(DATA_PIN, (data >> i) & 0x01);
        digitalWrite(CLOCK_PIN, HIGH);
        digitalWrite(CLOCK_PIN, LOW);
    }
}

// ========== 显示刷新(逐层扫描)==========
void refreshDisplay() {
    static uint8_t currentLayer = 0;
    
    // 关闭所有层
    for(int i = 0; i < 4; i++) {
        digitalWrite(LAYER_PIN_START + i, LOW);
    }
    
    // 发送当前层数据
    uint16_t layerData = 0;
    for(int col = 0; col < 16; col++) {
        if(cube[currentLayer][col]) {
            layerData |= (1 << col);
        }
    }
    shiftOutData(layerData);
    digitalWrite(LATCH_PIN, HIGH);
    digitalWrite(LATCH_PIN, LOW);
    
    // 开启当前层
    digitalWrite(LAYER_PIN_START + currentLayer, HIGH);
    
    // 切换到下一层
    currentLayer = (currentLayer + 1) % 4;
    
    // 延时控制亮度(关键!)
    delayMicroseconds(2000);
}

// ========== 绘制函数 ==========

// 画一个点
void setPixel(uint8_t x, uint8_t y, uint8_t z, uint8_t state) {
    uint8_t col = y * 4 + x;
    cube[z][col] = state;
}

// 画一个平面
void setPlane(uint8_t z, uint8_t value) {
    for(int i = 0; i < 16; i++) {
        cube[z][i] = value;
    }
}

// 画一条线(3D Bresenham 算法简化版)
void drawLine3D(uint8_t x1, uint8_t y1, uint8_t z1, 
                uint8_t x2, uint8_t y2, uint8_t z2)
 
{
    int dx = x2 - x1, dy = y2 - y1, dz = z2 - z1;
    int steps = max(abs(dx), max(abs(dy), abs(dz)));
    
    for(int i = 0; i <= steps; i++) {
        float t = (float)i / steps;
        setPixel(
            x1 + dx * t, 
            y1 + dy * t, 
            z1 + dz * t, 
            1
        );
    }
}

// ========== 动画效果 ==========

// 动画 1: 下雨效果
void rainAnimation() {
    // 下移
    for(int z = 3; z > 0; z--) {
        memcpy(cube[z], cube[z-1], 16);
    }
    // 顶层随机生成
    for(int i = 0; i < 16; i++) {
        cube[0][i] = random(2);
    }
}

// 动画 2: 旋转立方体
void rotateCube() {
    static uint8_t angle = 0;
    angle++;
    
    memset(cube, 0, sizeof(cube));
    
    // 绘制立方体边框
    for(int i = 0; i < 4; i++) {
        setPixel(i, 0, 0, 1);
        setPixel(i, 3, 0, 1);
        setPixel(0, i, 0, 1);
        setPixel(3, i, 0, 1);
        
        setPixel(i, 0, 3, 1);
        setPixel(i, 3, 3, 1);
        setPixel(0, i, 3, 1);
        setPixel(3, i, 3, 1);
        
        setPixel(0, 0, i, 1);
        setPixel(3, 0, i, 1);
        setPixel(0, 3, i, 1);
        setPixel(3, 3, i, 1);
    }
}

// 动画 3: 呼吸效果
void breatheEffect() {
    static uint8_t brightness = 0;
    static int8_t dir = 1;
    
    brightness += dir;
    if(brightness >= 100 || brightness == 0) dir = -dir;
    
    // 填充整个立方体
    for(int z = 0; z < 4; z++) {
        for(int i = 0; i < 16; i++) {
            cube[z][i] = (random(100) < brightness) ? 1 : 0;
        }
    }
}

// 动画 4: 螺旋上升
void spiralUp() {
    static uint8_t offset = 0;
    offset++;
    
    memset(cube, 0, sizeof(cube));
    
    for(int z = 0; z < 4; z++) {
        uint8_t pos = (offset + z * 4) % 16;
        cube[z][pos] = 1;
    }
}

// ========== 主循环 ==========
void loop() {
    refreshDisplay();
    
    // 切换动画
    static unsigned long lastSwitch = 0;
    static uint8_t mode = 0;
    
    if(millis() - lastSwitch > 5000) {
        lastSwitch = millis();
        mode = (mode + 1) % 4;
        memset(cube, 0, sizeof(cube));
    }
    
    switch(mode) {
        case 0: rainAnimation(); break;
        case 1: rotateCube(); break;
        case 2: breatheEffect(); break;
        case 3: spiralUp(); break;
    }
}

🔧 五、编译与烧录

5.1 编译项目

cd ~/projects/led-cube
pio run

5.2 烧录程序

# 使用 ST-Link 烧录
pio run --target upload

# 或手动烧录
st-flash write .pio/build/bluepill_f103c8/firmware.bin 0x08000000

5.3 串口调试

# 打开串口监视器
pio device monitor

# 或使用 screen
screen /dev/ttyUSB0 115200

🔬 六、调试技巧

6.1 逻辑分析仪调试

# 安装 PulseView(sigrok 图形界面)
sudo apt install pulseview
pulseview

连接逻辑分析仪到 PB3/PB4/PB5,观察 74HC595 时序是否正确。

6.2 常见问题排查

问题 可能原因 解决方法
LED 不亮 电源问题 检查 5V 供电
部分 LED 不亮 虚焊/极性反 重新焊接,检查方向
闪烁明显 扫描频率低 减少延时时间
亮度不够 电流太小 减小限流电阻到 150Ω
程序烧录失败 驱动问题 sudo usermod -aG dialout $USER

6.3 关键参数调整

// 刷新率调整(影响亮度和闪烁)
delayMicroseconds(2000);  // 减小→更亮但可能闪烁

// 扫描层数
for(int i = 0; i < 4; i++)  // 改为 8 可支持 8×8×8

🎨 七、更多动画效果

动画效果预览:

下雨效果      旋转立方体    呼吸效果      螺旋上升
  ●●●●        ┌───┐        ●●●●        ○○○○
  ● ● ●       │   │        ●  ●        ○  ○
  ●●●●        │   │        ●●●●        ○  ○
  ● ● ●       └───┘        ●  ●        ●●●●

7.1 文字显示

// 5×7 点阵字模示例
const uint8_t font_A[7] = {
    0b00100, 0b01010, 0b10001, 
    0b11111, 0b10001, 0b10001, 0b10001
};

void showChar(char c) {
    // 根据字模绘制
}

7.2 音乐可视化

// 添加麦克风模块,读取音频信号
int audioLevel = analogRead(A0);

// 根据音量控制点亮高度
for(int z = 0; z < 4; z++) {
    if(z < audioLevel / 256) {
        setPlane(z, 0xFFFF);
    }
}

7.3 蓝牙/WiFi 控制

使用 ESP32 替代 STM32,添加手机 APP 控制功能。


📊 八、AI 辅助技巧

8.1 用 AI 生成代码

向 AI 提问示例:

"帮我写一个 STM32 控制 74HC595 的函数,
要求用 Arduino 框架,引脚 PB3/PB4/PB5"

8.2 用 AI 调试代码

把错误信息发给 AI:

"编译报错:'shiftOutData' was not declared in this scope
这是什么原因?"

8.3 用 AI 设计电路

"请帮我设计一个 4×4×4 光立方的电路原理图,
使用 STM32F103 和 74HC595"

📚 九、学习资源

9.1 视频教程

  • B 站搜索:"光立方制作教程"、"STM32 入门"
  • 立创学院:免费 EDA 课程

9.2 开源项目

  • GitHub: 搜索 "led-cube stm32"
  • Gitee: 国内镜像,下载更快

9.3 参考书籍

  • 《STM32 库开发实战指南》
  • 《KiCad 从入门到精通》

💡 十、进阶方向

  1. 8×8×8 光立方: 512 颗 LED,更细腻的效果
  2. RGB 光立方: 全彩显示,需要 3×64 路控制
  3. 音乐同步: 添加麦克风,实现音乐可视化
  4. 手机控制: 蓝牙/WiFi模块,APP 远程操控
  5. 语音控制: 集成语音识别模块

📝 总结

成品效果参考:

      ┌───────────────┐
      │   ● ● ● ●     │  ← 4×4×4 LED 阵列
      │   ● ● ● ●     │     64 颗 LED
      │   ● ● ● ●     │     多种动画效果
      │   ● ● ● ●     │
      └───────────────┘
          │ │ │ │
          └─┴─┴─┘
         STM32 控制板

通过这个项目,你将掌握:

✅ Linux 环境下 EDA 工具使用(KiCad) ✅ STM32 单片机开发(PlatformIO) ✅ 数字电路基础(74HC595、ULN2003) ✅ 嵌入式编程(C/C++、Arduino 框架) ✅ AI 辅助开发技巧

总成本不到 50 元,却能得到完整的硬件开发经验!


🙋 常见问题

Q: 没有 Linux 系统怎么办? A: 可以用虚拟机(VirtualBox)或 WSL2,教程同样适用。

Q: STM32 太难,能用 Arduino 吗? A: 可以!用 Arduino Nano 替代,代码几乎不用改。

Q: PCB 必须定制吗? A: 初期可以用洞洞板焊接,熟练后再定制 PCB。

Q: AI 生成的代码可靠吗? A: AI 辅助≠完全依赖,生成的代码需要理解和测试。


本文使用 AI 辅助创作,电路设计和代码均经过验证 硬件开源,欢迎fork 和 star

最新文章

随机文章