本帖最后由 云天 于 2026-7-26 23:07 编辑
【项目简介】在传统风扇或扇子的使用场景中,用户通常只能通过物理开关或旋钮来调节风速和灯光。本项目尝试了一种全新的交互方式——通过触摸一条柔性传感器条的不同位置,同时控制扇子摆动速度和灯光亮度。手指在传感器上滑动,扇子摆动的节奏和灯光的明暗随之同步变化,带来一种仿佛“指挥”扇子的奇妙体验。 项目的核心创意来源于长条形薄膜位置传感器独特的形态——它不是旋钮,不是滑条,而是一条可以弯曲、贴附在任意表面的柔性薄膜。这种传感器形态天然适合与扇子、弧形表面等非平面结构结合,让交互方式更加自然和直观。 【硬件清单】
硬件 | 型号/SKU | 数量 | 说明 | | 主控板 | Arduino UNO R3 | 1 | 项目大脑 | | 薄膜位置传感器 | DFRobot SEN0690(300mm) | 1 | 输入:感知触摸位置 | | DAC模块 | DFRobot DFR1229(GP8600,16bit) | 1 | 输出:将数字信号转为0-5V模拟电压控制灯光- | | 舵机 | DSS-M15S 15KG 270度金属舵机 | 1 | 执行器:带动扇子摆动 | | 柔性灯丝 | 3V 260mm 柔性软灯丝 | 1 | 输出:可弯曲的360°发光灯丝 | | 电源 | 舵机独立供电(5V/6V) | 1 | 舵机电流较大,需单独供电 |

核心硬件亮点长条形薄膜位置传感器(SEN0690) 是一款基于石墨烯压感技术的柔性传感器。它的厚度仅0.45mm,可以弯曲贴合各种曲面。位置检测精度高达±2mm,响应速度<1ms,通过模拟量输出连续的位置信号。传感器采用3引脚连接,原生兼容Arduino平台。 GP8600 DAC模块(DFR1229) 是一款16bit高分辨率的数模转换模块,满量程误差仅±0.2%。它支持I2C或PWM信号驱动,可配置为0-5V、0-10V电压信号或4-20mA电流信号输出。I2C模式下,数值0-65535对应0-6V输出。 3V 260mm柔性软灯丝直径仅2mm,可任意弯曲折叠,360°发光无死角,,非常适合固定在扇子边缘作为装饰光源。
【硬件连接】按照下图连接各模块:
模块 | 引脚 | 连接至 | | 薄膜位置传感器 | VCC | Arduino 5V | | 薄膜位置传感器 | GND | Arduino GND | | 薄膜位置传感器 | OUT | Arduino A0 | | 舵机 | 信号线 | Arduino D9 | | 舵机 | VCC/GND | 独立电源(5V/6V) | | GP8600 DAC | VCC | Arduino 5V | | GP8600 DAC | GND | Arduino GND | | GP8600 DAC | SCL | Arduino A5(SCL) | | GP8600 DAC | SDA | Arduino A4(SDA) | | GP8600 DAC | OUT | 柔性灯丝正极(串接限流电阻) | | 柔性灯丝 | 负极 | GND |

特别注意: 舵机工作时电流较大(尤其带动扇叶时),务必使用独立电源为舵机供电,避免从Arduino取电导致主控复位。 柔性灯丝为3V规格,DAC模块输出的是0-5V电压,需要串联限流电阻(推荐47Ω-100Ω)保护灯丝。 GP8600模块的I2C地址默认为0x58,无需额外配置。
【工作原理信号流程】
手指触摸传感器 → 模拟电压变化 (0-5V) → Arduino读取ADC值 (0-1023)
↓ 分支1: 映射为舵机间隔时间 (100-1000ms) → 舵机在45°和135°之间往复摆动
分支2: 映射为DAC数值 (0-65535) → GP8600输出0-5V模拟电压 → 控制灯丝亮度控制逻辑
传感器读取:Arduino通过A0引脚读取传感器的模拟电压值,范围0-1023。传感器全长300mm,位置检测精度±2mm,手指在传感器上滑动时,ADC值会连续、线性地变化。 舵机控制:ADC值被映射为100-1000ms的间隔时间。ADC值越高(手指越靠近传感器末端),间隔时间越短,扇子摆动越快;ADC值越低,摆动越慢。舵机在45°和135° 之间循环摆动,形成“扇风”效果。 灯光控制:ADC值先转换为位置比例(0~1),再经非线性映射后转为DAC数值(0-65535),通过I2C总线发送给GP8600模块。模块输出对应的0-5V模拟电压驱动柔性灯丝。 为什么使用DAC模块而不是PWM直接驱动? Arduino的PWM输出是方波信号,直接驱动灯丝会产生频闪,且亮度调节线性度不佳。GP8600 DAC模块将数字信号转换为纯净的模拟电压,不仅调光更平滑,还支持0-5V/0-10V等多档输出范围,适配更多类型的灯光设备。 【完整代码】
- /*!
- * 智能扇子 - 薄膜位置传感器控制舵机摆动间隔 + DAC控制灯丝亮度
- * 硬件:Arduino UNO + SEN0690薄膜位置传感器 + DFR1229 GP8600 DAC + 舵机 + 柔性灯丝
- */
- #include <Servo.h>
- #include <DFRobot_GP8XXX.h>
-
- // ==================== 舵机部分 ====================
- Servo servo_9;
- volatile unsigned long lastSwitchTime; // 上次切换时刻
- volatile bool switchState = 0; // 0→45°,1→135°
- volatile unsigned long intervalTime; // 摆动间隔(毫秒)
-
- // ==================== DAC 部分 ====================
- #define I2C_COMMUNICATION
- #define MODULE_I2C_ADDRESS 0x58 // GP8600默认I2C地址
- DFRobot_GP8600_I2C GP8600(&Wire, MODULE_I2C_ADDRESS);
-
- const int sensorPin = A0; // 传感器接A0
- const float Vcc = 5.0;
- const float totalLength = 300.0; // 传感器总长300mm[reference:19]
-
- const int CHANGE_THRESHOLD = 3; // ADC变化死区(防抖动)
- const int MIN_ADC_THRESHOLD = 10; // 最小有效ADC阈值
- const float POWER = 1.0; // 映射指数(1.0=线性,0.5=低端更亮)
-
- int lastADC = -1;
-
- void setup() {
- Serial.begin(9600);
-
- // ---- 初始化舵机 ----
- servo_9.attach(9);
- lastSwitchTime = millis();
- switchState = 0;
- intervalTime = 500; // 初始间隔500ms
-
- // ---- 初始化DAC模块 ----
- while (GP8600.begin() != 0) {
- Serial.println("DAC模块连接失败,请检查接线!");
- delay(1000);
- }
- GP8600.setDACOutRange(GP8600.eOutputRange5V); // 设置为0-5V输出范围[reference:20]
- Serial.println("系统初始化完成!");
- }
-
- void loop() {
- int rawADC = analogRead(sensorPin); // 读取传感器值 0-1023
-
- // ========== 舵机控制 ==========
- if (rawADC > MIN_ADC_THRESHOLD) {
- // ADC 0→1000ms,1023→100ms(值越大,摆动越快)
- intervalTime = map(rawADC, 0, 1023, 1000, 100);
- }
-
- // 计时切换舵机角度
- if ((millis() - lastSwitchTime) > intervalTime) {
- lastSwitchTime = millis();
- if (switchState == 0) {
- servo_9.write(45); // 角度1
- } else {
- servo_9.write(135); // 角度2
- }
- switchState = !switchState; // 状态翻转
- }
-
- // ========== DAC控制(灯丝亮度) ==========
- if (rawADC > MIN_ADC_THRESHOLD) {
- if (abs(rawADC - lastADC) > CHANGE_THRESHOLD) {
- // 计算位置(mm)
- float rawVoltage = rawADC * (Vcc / 1023.0);
- float position = (rawVoltage / Vcc) * totalLength;
- position = constrain(position, 0.0, totalLength);
-
- // 位置比例 → DAC数值(非线性映射)
- float posRatio = position / totalLength; // 0~1
- float dacFloat = pow(posRatio, POWER) * 65535.0; // 0~65535[reference:21]
- uint16_t dacValue = (uint16_t)constrain(dacFloat, 0, 65535);
-
- // 通过I2C发送DAC数值[reference:22]
- GP8600.setDACOutData(dacValue);
- lastADC = rawADC;
-
- // 串口调试信息
- Serial.print("ADC:");
- Serial.print(rawADC);
- Serial.print(" Pos:");
- Serial.print(position);
- Serial.print("mm DAC:");
- Serial.print(dacValue);
- Serial.print(" Interval:");
- Serial.println(intervalTime);
- }
- }
- // 若rawADC <= MIN_ADC_THRESHOLD,保持上次DAC输出(灯丝维持当前亮度)
-
- delay(50); // 降低循环频率,减少串口输出压力
- }
复制代码 代码要点说明舵机间隔映射:map(rawADC, 0, 1023, 1000, 100) 将ADC值反向映射为间隔时间。手指在传感器起始端(ADC≈0)时,间隔1000ms(慢速);在末端(ADC≈1023)时,间隔100ms(快速)。 DAC输出范围:I2C模式下,GP8600的数值范围是0-65535,对应0-6V输出。代码中通过GP8600.setDACOutRange(GP8600.eOutputRange5V)将输出限制在0-5V范围内。 非线性映射:POWER参数控制亮度变化曲线。POWER=1.0为线性;POWER=0.5时低位置输出更大(低端更亮);POWER=2.0时低位置输出更小(低端更暗)。可根据实际效果调整。 防抖处理:CHANGE_THRESHOLD=3确保ADC变化超过3个值时才更新DAC,避免信号抖动导致灯光闪烁。
【结构安装】
建议扇子制作
传感器固定长条形薄膜位置传感器背部预置了双面胶,可直接粘贴在桌子的侧面。传感器厚度仅0.45mm,几乎不占空间,且可弯曲贴合弧形表面。 安装示意 [扇面]
/ | \
灯丝-----[舵机]-----灯丝
\ | /
[手柄]
|
[薄膜位置传感器] ← 手指滑动控制
|
[Arduino + DAC模块] 
【效果展示】

玩法交互方式轻触传感器起始端 → 舵机慢速摆动(≈1秒一个来回)+ 灯丝较暗 滑动到传感器中部 → 舵机中速摆动 + 灯丝中等亮度 按压传感器末端 → 舵机快速摆动(≈0.2秒一个来回)+ 灯丝最亮
与旋钮方案对比 传统旋钮电位器只能提供旋转这一种交互方式,而长条形薄膜位置传感器提供了沿直线滑动的交互体验。对于扇子这种长条形结构,滑动操作比旋转旋钮更加直观和自然——手指滑过的距离,直接对应扇子工作的强度。此外,传感器的柔性特性允许它贴合在任意形状的表面(弧形手柄、圆柱底座等),这是刚性旋钮无法实现的。 【总结】本项目展示了长条形薄膜位置传感器与高精度DAC模块在创意交互装置中的应用潜力。通过一个简单的滑动动作,同时控制舵机的摆动节奏和灯光的明暗变化,实现了“一触双控”的直观交互。
|