恒美微站
首页
关于我们
建站服务
主题模板
案例展示
资讯中心
联系我们
利用STM32与视觉暂留效应,将旧风扇改造为悬浮时钟的完整实践
首页
资讯中心
/
利用STM32与视觉暂留效应,将旧风扇改造为悬浮时钟的完整实践
利用STM32与视觉暂留效应,将旧风扇改造为悬浮时钟的完整实践
发布时间:2026/8/19 3:05:10
1. 项目缘起从废弃风扇到视觉暂留时钟的奇思妙想不知道你有没有这样的经历家里淘汰下来的旧电脑风扇或者从某个废旧电器上拆下来的小风扇总觉得丢了可惜留着又占地方。我之前就攒了好几个一直琢磨着怎么把它们“废物利用”起来。直到有一次我在网上看到一个利用视觉暂留效应制作的LED摇棒灵光一闪——风扇本身不就是一个高速旋转的“摇棒”吗如果能在扇叶上安装LED让它旋转起来显示图案岂不是天然的POV显示平台这个想法让我兴奋了好一阵子。POV全称Persistence of Vision即视觉暂留效应。简单来说就是当物体快速移动时人眼看到的图像会在视网膜上短暂停留约0.1秒。利用这个原理让一排高速移动的LED灯按特定时序点亮我们就能在空中“画”出稳定的图案或文字。而一个高速旋转的风扇其扇叶轨迹恰好形成了一个圆形的显示区域简直是制作圆形POV时钟的绝佳载体。那么显示什么呢时钟无疑是最实用、也最酷的选择。它既有实用价值又能完美展示POV技术的魅力——一个看似空无一物的风扇一旦转起来时间便悬浮在空中。为了实现精准计时我选择了经典的DS1307实时时钟芯片。它价格低廉、接口简单I2C、自带电池备份即使主系统断电时间也能继续走是这类DIY项目的常客。整个项目的核心就是让一个旧风扇“重生”变成一个能悬浮显示时间的酷炫时钟。2. 核心硬件选型与改造风扇、主控与RTC的搭配逻辑动手之前得先把硬件家底摸清并想清楚为什么选它们。这不是简单的零件堆砌每个选择背后都有成本和性能的权衡。2.1 风扇的“手术”从散热器到显示载体首先是最关键的显示载体——风扇。我手头有几个12V的机箱风扇尺寸从8cm到12cm不等。我最终选择了一个9cm的旧CPU散热风扇。为什么是它有几个考量第一尺寸适中9cm的显示面积在桌面上既不显得笨重信息量也足够第二大多数电脑风扇是无刷直流电机由定子线圈和转子磁铁扇叶构成我们需要改造的是旋转的转子部分第三它的轴是通孔的方便我们穿过导线。改造风扇是第一步也是最需要耐心的一步。我们的目标是在每个扇叶的尖端安装一颗LED。这样当风扇旋转时这些LED就会形成一个圆环。我选择了常见的5mm雾状蓝色LED亮度高扩散效果好在视觉暂留下线条更连续。拆下扇叶后我在每个扇叶尖端用细钻头打一个小孔刚好能紧密嵌入LED。这里有个关键细节LED的引脚必须用极细的漆包线比如AWG 38连接并且要从风扇中心轴的空洞穿出。粗线会增加旋转阻力并带来安全隐患。将漆包线沿着扇叶背面用耐高温胶带或少量热熔胶固定最后所有LED的阴极短脚并联阳极长脚则分别引出为后续的单独控制做准备。2.2 主控大脑为什么是STM32而不是Arduino接下来是控制核心。很多人第一时间会想到Arduino它确实简单易用。但我选择了STM32F103C8T6即常说的“蓝色药丸”。原因有三第一性能与实时性。POV显示对时序要求极其苛刻STM32的72MHz主频远超Arduino UNO的16MHz能提供更精准的定时中断来控制LED点亮瞬间确保显示稳定不抖动。第二外设与内存。STM32有丰富的定时器和DMA直接存储器访问资源我们可以用高级定时器的PWM输出配合DMA几乎不占用CPU资源就能生成复杂的LED控制信号。第三功耗与扩展。本项目最终希望由电池供电STM32的低功耗模式如Standby模式配合RTC唤醒能极大延长续航这正是网络热词“stm32f103 standby rtc唤醒”所指向的应用场景。2.3 时间之心DS1307 RTC芯片的可靠性与局限计时核心DS1307这是一个老牌且经典的RTC芯片。它通过I2C接口与主控通信自带56字节的NV SRAM最关键的是它有一个独立的电池备份引脚VBAT。当主电源VCC断开时芯片会自动切换到纽扣电池供电保证时钟持续运行。我选择它一是因为其电路简单只需外接一个32.768kHz的晶振和两个负载电容即可工作二是因为资料丰富任何问题基本都能找到答案。但它也有缺点精度一般约±2分钟/月且I2C通信速度较慢。对于时钟项目精度可以通过软件定期校准来改善而通信速度在每次读取时间最多7字节时的影响微乎其微完全可接受。一个重要的实操心得DS1307对晶振和电容的匹配比较敏感。务必按照数据手册推荐使用负载电容为12.5pF的晶振并且PCB布线时让晶振尽量靠近芯片引脚走线对称这样可以减少起振困难和频率偏差。2.4 供电与信号传输旋转部分的“生命线”如何给旋转的扇叶上的LED供电和传输控制信号这里有两个主流方案滑环和无线供电如电磁感应。滑环可靠但会有磨损和噪音无线供电电路稍复杂。为了追求静音和耐用性我采用了简化版的电磁感应供电。在风扇底座固定一个初级线圈通以高频交流电在转子背面贴一个次级线圈和整流稳压电路即可实现非接触供电。信号传输则采用红外对管在底座安装一个红外发射管在转子底部对应位置安装接收管。风扇每旋转一圈接收管会收到一次脉冲作为帧同步信号告诉主控“新的一圈开始了”这是保证显示内容不旋转错位的关键。注意改造风扇涉及电路和高速旋转物体务必确保所有焊接牢固导线固定稳妥并在低压如5V下初步测试旋转平衡性防止高速运行时零件脱落发生危险。3. 系统架构与核心电路设计要点硬件选型确定后需要把它们有机地组合起来。整个系统可以分为旋转显示模块和固定主控模块两大部分它们之间通过无线供电和红外信号进行能量与同步信息的交互。3.1 旋转显示模块简约而不简单这个模块位于风扇转子上随扇叶一起旋转。其核心是一个多通道的LED驱动电路。由于我们需要独立控制每个扇叶上的LED以显示不同数字的笔画所以不能简单地将所有LED并联。我使用了德州仪器的TLC5940这款LED驱动芯片。它是一款16通道的恒流驱动芯片每个通道可以独立设置PWM灰度值。这意味着我们不仅可以控制LED亮灭未来还能扩展为调节亮度显示更丰富的效果。旋转模块的电路板需要做得很小、很轻并做好动平衡。PCB设计成圆形中心开孔穿过风扇轴。上面集成TLC5940、红外接收管、稳压芯片如AMS1117-3.3以及接收线圈的整流滤波电路。TLC5940通过SPI接口接收来自主控的数据经过电平转换和信号耦合。这里的一个关键设计是电源管理接收线圈感应到的电压先经过整流桥和滤波电容然后输入一个低压差线性稳压器LDO得到稳定的3.3V。电容的容量要足够大以储存能量应对线圈感应电压瞬间波动的状况。3.2 固定主控模块控制与计算中枢这个模块固定在风扇底座不旋转。它以STM32F103为核心周围环绕着几个关键电路DS1307电路包括DS1307芯片、32.768kHz晶振Y1、两个22pF的负载电容C1, C2、一个3V的纽扣电池座BT1以及I2C的上拉电阻R1, R2 通常为4.7kΩ。VBAT引脚直接接电池VCC接系统3.3V。红外同步电路一个简单的红外发射管IRED串联一个限流电阻如100Ω由STM32的一个IO口控制。发射管对准旋转路径确保每转一圈都能被转子底部的接收管检测到。无线供电发射电路这是一个由STM32定时器产生PWM方波驱动的H桥电路如IRF7309驱动初级线圈L1产生交变磁场。谐振电容C3与线圈电感形成LC谐振能提高传输效率。调试心得初级线圈的匝数和驱动频率需要匹配。通过测量线圈电感和计算谐振频率将PWM频率设定在谐振点附近通常在几百kHz可以获得最佳的能量传输效果。通信接口STM32通过一个由光耦或电容耦合构成的简易隔离电路将SPI数据发送给旋转模块上的TLC5940。这样做是为了隔离旋转与固定部分的地避免噪声干扰。3.3 同步机制让时间“定格”在空中POV显示稳定与否关键在于同步。我们的同步机制是这样的硬同步帧起始风扇转子每旋转一圈其底部的红外接收管会接收到一次底座发射管发出的信号产生一个下降沿中断给STM32。这个中断被设置为最高优先级它标志着“新的一帧显示开始”STM32立即从显示缓冲区的起始位置开始发送LED数据。软同步时基分割一圈360度我们要显示60个刻度秒、12个小时刻度以及数字。STM32内部的一个高级定时器如TIM1被配置为向上计数模式其溢出频率设置为风扇转速RPS * 每圈显示点数N。例如风扇转速为1200 RPM即20 RPS我们希望每圈有360个显示点来保证圆环平滑那么定时器频率应设为 20 * 360 7.2 kHz。每次定时器溢出中断STM32就计算出当前角度对应的LED显示数据并通过DMA发送给TLC5940。这样就把时间定时器中断映射到了空间旋转角度上。这种“硬同步复位软同步插值”的方式即使风扇转速有微小波动显示的内容也不会扭曲或断裂只是整体略微缩放人眼几乎察觉不到。4. 固件程序设计从时间读取到空间绘制的全流程软件是项目的灵魂它需要高效地管理时间、处理同步信号、计算显示内容并驱动硬件。整个程序围绕中断和状态机展开。4.1 底层驱动初始化与时间接口首先初始化所有外设// 伪代码示例 void Hardware_Init(void) { // 1. 系统时钟配置72MHz RCC_Configuration(); // 2. 初始化I2C1用于DS1307通信 I2C_Init(); // 3. 初始化SPI1用于TLC5940通信并启用DMA SPI_DMA_Init(); // 4. 初始化高级定时器TIM1用于生成显示时基中断 TIM1_Init(); // 设置ARR为 (72000000 / 7200) - 1 // 5. 初始化一个外部中断引脚如EXTI0用于红外同步信号下降沿触发 EXTI_Sync_Init(); // 6. 初始化另一个定时器如TIM2用于红外发射管调制如38kHz载波 TIM2_Init(); // 7. 初始化RTC唤醒等相关低功耗功能备用 PWR_RTC_Init(); }DS1307的读写函数需要严格按照其时序编写。读时间时先写入要读取的寄存器地址0x00然后重新发起读请求连续读取7个字节秒、分、时、星期、日、月、年。4.2 核心算法将时间转换为LED点阵数据这是最具挑战性的部分。我们需要一个“画布”——一个在内存中代表360度圆环的显示缓冲区DisplayBuffer[360][N_LED]其中360是角度分辨率N_LED是LED数量例如4个扇叶就是4。每个元素是一个亮度值0-4095对应TLC5940的12位PWM。当从DS1307读取到当前时间时、分、秒后需要将其绘制到这个圆形画布上计算角度秒针角度second_angle (seconds % 60) * 6一圈360度60秒每秒6度分针角度minute_angle (minutes % 60) * 6 (seconds / 60.0) * 6加上秒带来的偏移更真实时针角度hour_angle (hours % 12) * 30 (minutes / 60.0) * 30一圈360度12小时每小时30度绘制表盘在缓冲区中将所有60个秒刻度每隔6度、12个小时刻度的位置对应的LED亮度设为某个值。例如在0度、90度、180度、270度位置绘制更粗的刻度。绘制指针这是一个反走样问题。指针不是一条完美的数学线它占据一个角度范围。例如绘制分针我们可以在minute_angle ± 0.5度的范围内将所有LED的亮度设为最大值。为了更平滑甚至可以实现简单的线性反走样角度差0.5度时亮度100%角度差1度时亮度50%。绘制数字这是难点。需要在圆形坐标系上绘制“12”、“3”、“6”、“9”等数字。我预先定义了几个数字的矢量字体用一系列角度和半径坐标表示笔画然后根据当前角度判断每个显示点角度半径是否落在某个笔画的矩形区域内。如果是则点亮该位置对应的LED。优化技巧这些判断计算量较大不要放在中断中进行。可以创建一个“脏标志”当时间改变时在主循环中重新计算整个显示缓冲区中断服务程序只负责搬运已计算好的缓冲区数据。4.3 中断服务程序精准的时序控制两个中断构成了显示引擎的核心// 红外同步中断最高优先级 void EXTI0_IRQHandler(void) { if(EXTI_GetITStatus(EXTI_Line0) ! RESET) { Display_Angle_Index 0; // 重置角度索引 TIM_SetCounter(TIM1, 0); // 重置定时器计数器确保严格同步 EXTI_ClearITPendingBit(EXTI_Line0); } } // 定时器中断显示时基 void TIM1_UP_IRQHandler(void) { if(TIM_GetITStatus(TIM1, TIM_IT_Update) ! RESET) { // 1. 根据当前 Display_Angle_Index从 DisplayBuffer 中取出对应角度的LED数据 uint16_t led_data[4] Get_LED_Data_At_Angle(Display_Angle_Index); // 2. 通过DMA将数据发送到SPI非阻塞高效 SPI_Send_Data_by_DMA(led_data); // 3. 角度索引递增准备下一个点 Display_Angle_Index (Display_Angle_Index 1) % 360; TIM_ClearITPendingBit(TIM1, TIM_IT_Update); } }通过DMA搬运SPI数据CPU在中断服务程序中的负担极轻大部分时间可以处于休眠状态这对于电池供电至关重要。4.4 低功耗策略让时钟持续运行数月如果希望用电池供电低功耗设计必不可少。STM32的Standby模式功耗极低约2μA但在此模式下大部分外设都会关闭包括定时器。然而DS1307的SQW/OUT引脚可以输出方波信号例如1Hz。我们可以将这个信号连接到STM32的唤醒引脚如WKUP。配置DS1307输出1Hz方波并使STM32进入Standby模式。每过1秒DS1307的方波上升沿就会将STM32从Standby模式唤醒。唤醒后STM32读取DS1307的时间更新显示缓冲区然后驱动风扇旋转显示几秒钟比如10秒随后再次进入Standby模式。这样绝大部分时间系统都在“深度睡眠”只有需要“刷新”显示时才短暂工作可以极大地延长电池寿命。这正是“stm32f103 standby rtc唤醒”的经典应用。5. 组装、调试与优化中的实战经验把所有模块焊接好代码编译下载只是万里长征第一步。真正的挑战在于让整个系统稳定、可靠、美观地运行起来。5.1 机械组装与动平衡调试将改造好的扇叶组件重新安装到风扇电机上。确保所有导线从轴心穿出后留有足够的松弛度防止旋转时拉扯。固定主控板在风扇底座调整红外发射管和初级线圈的位置使其与转子上的接收部分对准。动平衡是成败的关键。转子一侧增加了LED、线圈和小电路板必然导致重心偏移高速旋转时会产生剧烈震动和噪音。我的调试方法是将风扇通电低速旋转用手机慢动作视频拍摄观察抖动情况。然后在偏轻的扇叶背面非LED面一点点粘贴配重如小块电工胶带、焊锡反复试验直到在各个转速下都运行平稳。这个过程很枯燥但必不可少。5.2 电路调试电源、同步与通信无线供电调试先不接旋转模块用示波器或万用表测量初级线圈两端的电压波形调整PWM频率观察电压幅度变化找到谐振点电压幅度最大处。然后接上旋转模块在次级线圈输出端测量应有稳定的3.3V左右电压。如果带载后电压跌落严重可能需要增加初级驱动电流或优化线圈耦合距离通常1-3mm为宜。红外同步调试让风扇缓慢旋转可用于拨动用示波器观察红外接收管的输出信号。应该能看到一个清晰的、每转一圈出现一次的脉冲。如果信号杂乱可能是环境光干扰可以给接收管加上深色套管或者调制发射管电流用38kHz载波驱动接收端使用带解调功能的接收头如VS1838B。SPI通信调试这是最易出问题的地方。因为信号需要通过非接触方式传输我采用了电容耦合。在固定端SPI的MOSI信号通过一个100pF的电容连接到旋转端的接收电路。旋转端用一个施密特触发器如74HC14对耦合过来的信号进行整形再送给TLC5940。调试时先用杜邦线直连确保TLC5940能被正常驱动。然后改用耦合电路用示波器同时观察发送端和接收端的波形调整耦合电容容量直到接收端波形清晰、无严重畸变。5.3 软件调试与显示优化转速测量与自适应理想情况下我们希望显示内容大小固定不受转速影响。这需要知道实时转速。我们可以利用红外同步中断计算两个同步脉冲之间的时间间隔从而得到实时转速RPS 1 / 间隔时间。然后动态调整定时器TIM1的溢出频率即转速 * 每圈点数实现显示点密度的自适应让时钟看起来大小恒定。亮度与对比度在光线较强的环境下LED可能显得不够亮。可以通过提高TLC5940的驱动电流调整IREF电阻来解决。同时由于POV效应LED点亮时间极短微秒级实际视觉亮度与占空比PWM值不是线性关系需要根据实际效果建立一个亮度伽马校正表使亮度调节更符合人眼感知。图形抗锯齿直接绘制指针和数字会有明显的锯齿感。除了之前提到的角度反走样对于数字可以采用更高分辨率的虚拟画布进行计算然后下采样到实际的LED网格上能有效平滑边缘。5.4 常见问题与排查清单问题显示内容闪烁、断裂。排查首先检查红外同步信号是否稳定。用示波器锁定同步脉冲看其是否每圈一次且位置固定。其次检查定时器中断是否被更高优先级的中断长时间阻塞。确保显示相关的中断优先级最高。问题数字或指针显示位置漂移。排查同步信号正常但计算出的角度基准不对。检查Display_Angle_Index在同步中断中是否被正确重置为0。检查角度计算函数确认没有整数溢出或浮点数精度问题。问题旋转模块供电不稳定时亮时灭。排查测量次级线圈的整流输出电压。如果波动大增加滤波电容的容值如从100uF增加到470uF。检查线圈对齐情况和距离确保耦合良好。问题电机发热严重或转速不稳。排查动平衡没做好导致负载不均。重新进行配平。也可能是驱动风扇的电压或电流不足尝试提高供电电压在电机额定电压内。完成所有这些调试后一个由旧风扇改造的POV时钟就真正“活”了过来。看着它在空中清晰地显示着时间那种成就感远超购买一个成品。这个项目融合了机械改造、模拟/数字电路设计、嵌入式编程和算法是一个非常好的全栈式硬件学习实践。它教会我的不仅是技术更是一种将想法一步步变为现实的能力。如果你手边也有闲置风扇不妨试试这个悬浮于空中的时间魔法绝对能成为你工作台上最吸引眼球的装置。