用Arduino Nano和SG90舵机做个摇头风扇:从PWM原理到完整代码(附库文件)
2026/5/5 0:29:23 网站建设 项目流程

用Arduino Nano和SG90舵机打造智能摇头风扇:从硬件搭建到拟自然风算法

夏日的闷热总让人渴望一丝清凉,而自己动手制作一个能自动摇头的小风扇,不仅能解决实际需求,还能深入理解PWM控制与机电一体化的奥秘。这个项目将带你用不到百元的成本,实现市面上数百元智能风扇的核心功能——通过Arduino Nano控制SG90舵机,让普通风扇拥有拟人化的自然摆风效果。

1. 项目核心硬件解析

1.1 SG90舵机的控制奥秘

作为市面上最常见的微型舵机,SG90虽小却蕴含着精密的控制逻辑。其内部包含直流电机、减速齿轮组、电位器和控制电路,构成一个完整的闭环控制系统。当我们给黄线(信号线)发送PWM信号时,控制电路会比较电位器反馈的位置与输入信号对应的目标位置,驱动电机转动直到两者匹配。

关键参数对照表

参数SG90典型值项目应用要点
工作电压4.8V-6V需独立供电避免Arduino过载
堵转扭矩1.8kg·cm(6V)选择轻质扇叶确保扭矩足够
响应速度0.12s/60°(6V)影响摇头自然度
PWM频率50Hz(周期20ms)必须严格保持
脉冲宽度范围500-2500μs对应0-180°转动

1.2 Arduino Nano的PWM输出特性

与原始文章中51单片机需要手动配置定时器不同,Arduino生态已经为我们封装好了PWM控制。Nano的3、5、6、9、10、11引脚支持analogWrite()函数输出PWM,但要注意:

// 传统analogWrite()在舵机控制中的局限 void setup() { pinMode(9, OUTPUT); // 以9号引脚为例 analogWrite(9, 128); // 输出50%占空比 }

这种方法输出的PWM频率约为490Hz,远高于舵机需要的50Hz。因此我们需要使用Arduino内置的Servo库,它会自动重配置定时器来生成正确的PWM信号。

2. 硬件搭建与供电方案

2.1 安全可靠的接线方案

不同于简单的实验电路,摇头风扇需要长时间运行,必须考虑接线的可靠性:

  1. 信号线:SG90黄线 → Arduino Nano的D9(或其他支持Servo库的引脚)
  2. 电源系统
    • 推荐使用5V 2A以上的独立电源
    • 电源正极同时接Nano的VIN和舵机红线
    • 所有GND(Nano、舵机、电源)必须共地

注意:切勿通过Nano的5V引脚直接给舵机供电!舵机启动时的瞬间电流可能导致Nano重启。

2.2 机械结构设计要点

用3D打印或轻质材料制作支架时需考虑:

  • 重心位置应低于转轴,避免舵机负载过大
  • 扇叶直径建议10-15cm,过大可能超出舵机扭矩
  • 使用热熔胶固定时注意绝缘,避免短路风险

常见问题排查清单

  • 舵机抖动不转 → 检查供电是否充足
  • 转动角度不准确 → 校准PWM脉冲宽度
  • 运行时Arduino重启 → 电源功率不足或接线松动

3. 核心控制代码实现

3.1 基础扫频模式

我们先实现最简单的左右摆动效果:

#include <Servo.h> Servo myservo; int pos = 0; void setup() { myservo.attach(9); // 连接D9引脚 } void loop() { for (pos = 0; pos <= 180; pos += 1) { myservo.write(pos); delay(15); // 控制转速 } for (pos = 180; pos >= 0; pos -= 1) { myservo.write(pos); delay(15); } }

这段代码虽然简单,但存在机械感强、动作生硬的问题。接下来我们改进为更自然的随机摆风模式。

3.2 拟自然风算法进阶

模仿真实风扇的随机停顿和变速效果:

#include <Servo.h> #include <math.h> Servo fanServo; int currentPos = 90; int targetPos = 90; unsigned long lastChangeTime = 0; int changeInterval = 0; void setup() { fanServo.attach(9); randomSeed(analogRead(0)); // 初始化随机种子 } void loop() { if (millis() - lastChangeTime > changeInterval) { lastChangeTime = millis(); targetPos = random(60, 120); // 在60°-120°范围内随机选择新位置 changeInterval = random(1000, 3000); // 1-3秒随机间隔 // 添加缓动效果 float speedFactor = random(5, 15) / 10.0; int moveStep = (targetPos > currentPos) ? 1 : -1; while (abs(currentPos - targetPos) > 2) { currentPos += moveStep * speedFactor; fanServo.write(constrain(currentPos, 0, 180)); delay(30); } } }

这段代码实现了:

  • 随机目标位置选择
  • 可变的停顿间隔
  • 非线性缓动效果(类似CSS的easing)
  • 运动过程中的平滑过渡

4. 系统优化与功能扩展

4.1 能耗优化策略

长时间运行时需要考虑功耗问题:

  1. 使用servo.detach()在闲置时断开舵机电源
  2. 添加红外或超声波传感器,检测到有人时才启动
  3. 采用PID算法优化运动轨迹,减少无效转动

4.2 无线控制升级

通过蓝牙模块添加手机控制功能:

#include <SoftwareSerial.h> #include <Servo.h> SoftwareSerial BT(2, 3); // RX, TX Servo myServo; int lastAngle = 90; void setup() { Serial.begin(9600); BT.begin(9600); myServo.attach(9); myServo.write(lastAngle); } void loop() { if (BT.available()) { String command = BT.readStringUntil('\n'); command.trim(); if (command.startsWith("ANGLE:")) { int newAngle = command.substring(6).toInt(); newAngle = constrain(newAngle, 0, 180); // 平滑过渡 while (abs(lastAngle - newAngle) > 0) { lastAngle += (newAngle > lastAngle) ? 1 : -1; myServo.write(lastAngle); delay(20); } } } }

配合手机APP发送"ANGLE:90"这样的指令,即可实现远程控制。

4.3 风速联动控制

进阶方案可以添加PWM风扇控制,使风速随角度变化:

int fanSpeedPin = 5; // 连接风扇PWM控制线 void updateFanSpeed(int angle) { // 中间位置风速最大,两边递减 int speed = 255 - abs(angle - 90) * 2; analogWrite(fanSpeedPin, constrain(speed, 100, 255)); }

在每次舵机角度变化时调用此函数,即可实现风量随摇头位置自动调节的效果。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询