“Programming Fog”(编程雾)是一个面向嵌入式雾化控制场景的轻量级 Arduino 库,专为作者自研的同名硬件模块——
Programming Fog Board
(编程雾板)设计。该库并非通用型雾化驱动框架,而是深度耦合特定硬件电路的固件抽象层,其核心价值在于将复杂的高压雾化驱动逻辑封装为极简的、面向应用层的 C++ 接口,使硬件开发者能够以“功能即服务”的方式快速构建水雾交互系统。
从工程定位看,Programming Fog 板本质上是一块
高可靠性雾化执行器接口板
,它解决了传统 DIY 雾化项目中长期存在的两个关键痛点:
-
启停不可控性
:多数雾化模块仅支持硬开关或简易 PWM 控制,缺乏明确的使能/禁用状态机,易导致误触发、残留雾化或继电器/固态继电器(SSR)触点粘连; -
雾量调节粗糙化
:常见方案依赖固定占空比 PWM 或电位器分压,无法实现与模拟传感器(如旋钮、光敏电阻、电容式触摸滑条)的线性、实时、无抖动映射。
本库通过在硬件层集成专用驱动电路(推测含光耦隔离、MOSFET/IGBT 驱动级、过流保护及模拟信号调理),配合软件层简洁 API,实现了对超声波雾化片(典型工作频率 1.7MHz)或高压柱塞泵等执行机构的
数字使能控制 + 模拟量雾量闭环调节
双模能力。其目标应用场景明确指向教育实验、艺术装置、环境模拟、小型加湿/香薰设备等对交互性、可编程性要求高于工业级稳定性的领域。
2.1 编程雾板核心电路拓扑
尽管 README 未提供原理图,但基于其功能描述与引脚定义,可逆向推导出该板的典型硬件架构:
电源输入
雾化使能驱动
雾量模拟调节
关键设计洞察
:A0 引脚被指定为模拟输入,且文档强调“based on a simple 5V analogRead value”,表明该板内部已集成
5V 基准电压源
,确保 ADC 读数不受外部 VCC 波动影响。此设计显著优于依赖 MCU 内部 VREF 的方案,提升了雾量调节的绝对精度与重复性。
2.2 物理连接规范
编程雾板采用极简三线制连接,极大降低了硬件接入门槛:
VCC
严禁接 3.3V!
否则可能导致 ADC 量程错误或驱动不足。
GND
A0
唯一数据通道
。用于接收用户设定的雾量控制值。需确保 Arduino 的 A0 引脚配置为
INPUT
模式。
实践警告
:该板未暴露任何 UART、I2C 或 SPI 接口,意味着所有通信均通过模拟电压完成。这既是其“简单性”的体现,也决定了其
不适用于需要高速反馈(如雾化状态监测)、多设备级联或远程参数配置的场景
。工程师在选型时需明确此边界。
Programming Fog 库以
Fog
类封装全部功能,遵循 Arduino C++ 库标准结构(
Fog.h
/
Fog.cpp
)。其 API 设计极度精简,仅暴露 4 个公有成员函数,但每个函数背后均隐含严谨的状态管理与硬件时序控制。
3.1 初始化函数:
FogInit()
FogInit()
// 在 Arduino Sketch 的 setup() 中调用
void setup() {
Fog fog; // 创建 Fog 对象实例
fog.FogInit(); // 执行硬件初始化
// ... 其他初始化代码
}
函数签名
:
void Fog::FogInit()
底层实现逻辑(基于典型 Arduino 库惯例推断)
:
-
GPIO 配置
:将控制雾化使能的 MCU 引脚(具体引脚号由库内部
#define
固定,如
FOG_ENABLE_PIN
)配置为
OUTPUT
,并初始化为
LOW
(确保上电瞬间雾化器处于关闭状态); -
ADC 初始化
:调用
analogReference(DEFAULT)
或
analogReference(INTERNAL)
(若板载有 1.1V 基准)确保 ADC 参考电压与硬件设计一致;
analogReadResolution(10)
显式设置为 10 位(匹配 0–1023 范围); -
状态机复位
:将内部状态变量(如
isFogRunning
)置为
false
,清除任何潜在的初始错误标志。
工程要点
:
-
必须在
setup()
中调用,且仅调用一次
。重复调用可能导致 GPIO 重配置冲突; -
若项目中需动态切换雾化板,应将
Fog
对象声明为全局变量,避免在
loop()
中频繁构造/析构对象。
3.2 启动函数:
FogOn()
FogOn()
// 启动连续最大功率雾化
fog.FogOn();
函数签名
:
void Fog::FogOn()
行为规范
:
-
立即拉高雾化使能控制线(对应 MCU GPIO 输出
HIGH
); -
忽略当前 A0 输入值
,强制驱动雾化器以硬件允许的最大功率持续工作; -
不改变内部状态变量
fogAmount
,为后续
FogAnalog()
调用保留上下文。
典型应用场景
:
- 快速演示模式(如展会一键启动);
-
作为
FogAnalog()
的安全兜底:先
FogOn()
确保雾化器已激活,再
FogAnalog(1023)
达到满功率; - 与按钮中断结合,实现“长按启动”逻辑。
3.3 停止函数:
FogOff()
FogOff()
// 彻底停止雾化
fog.FogOff();
函数签名
:
void Fog::FogOff()
行为规范
:
-
立即拉低雾化使能控制线(对应 MCU GPIO 输出
LOW
); -
切断所有能量供给
,雾化器物理停止工作,无任何残余雾气; -
将内部状态
isFogRunning
置为
false
。
关键工程价值
:
- 解决了传统方案中“PWM 占空比=0%”仍可能因驱动电路特性产生微弱雾化的顽疾;
- 为安全机制(如温度超限、水位不足)提供确定性的紧急停机入口;
-
在
loop()
中可与传感器读数结合,实现自动关机(例:
if (waterLevel < THRESHOLD) fog.FogOff();
)。
3.4 模拟量雾量控制函数:
FogAnalog(int inputValue)
FogAnalog(int inputValue)
// 根据 A0 读数实时控制雾量
int sensorValue = analogRead(A0); // 读取外部模拟信号(0-1023)
fog.FogAnalog(sensorValue);
函数签名
:
void Fog::FogAnalog(int inputValue)
参数详解
:
inputValue
analogRead(A0)
获取的原始 ADC 值。
库内部不做范围检查,越界值将导致未定义行为
。
内部处理流程
:
-
范围钳位(推荐在调用前由用户完成)
:inputValue = constrain(inputValue, 0, 1023); // 防止传感器异常导致失控 -
线性映射
:将
inputValue
(0–1023)直接映射至驱动级的控制信号(推测为 PWM 占空比 0%–100%,或 DAC 输出电压 0V–5V); -
输出更新
:将计算结果写入对应的定时器寄存器(如
OCR1A
)或 DAC 寄存器,立即生效。
性能特征
:
-
实时性高
:单次调用耗时通常 < 10μs(纯寄存器操作),适合 100Hz 以上动态调节; -
无内置滤波
:库本身不进行软件滤波,雾量响应与 A0 电压变化严格同步。若需平滑,须在
analogRead()
后添加移动平均或 IIR 滤波。
高级应用示例(FreeRTOS 集成)
:
// 在 FreeRTOS 任务中实现带滤波的雾量控制
void fogControlTask(void *pvParameters) {
Fog fog;
fog.FogInit();
const int FILTER_SIZE = 5;
int filterBuffer[FILTER_SIZE] = {0};
int filterIndex = 0;
int filteredValue = 0;
while(1) {
int raw = analogRead(A0);
// 简单移动平均滤波
filterBuffer[filterIndex] = raw;
filterIndex = (filterIndex + 1) % FILTER_SIZE;
filteredValue = 0;
for(int i = 0; i < FILTER_SIZE; i++) filteredValue += filterBuffer[i];
filteredValue /= FILTER_SIZE;
fog.FogAnalog(constrain(filteredValue, 0, 1023));
vTaskDelay(pdMS_TO_TICKS(50)); // 20Hz 更新率
}
}
4.1 DIY 智能香薰机(闭环湿度控制)
系统构成
:Programming Fog 板 + Arduino Uno + DHT22 温湿度传感器 + 旋转电位器(手动调节)
设计逻辑
:
- 电位器连接 A0,提供用户期望的“目标雾量等级”(0–1023);
-
DHT22 实时读取环境湿度
currentHumidity
; -
MCU 计算偏差
error = targetHumidity - currentHumidity
; -
使用比例控制(P-Control):
output = Kp * error
,将
output
与电位器值融合(如
finalValue = map(output, -100, 100, 0, 1023) + potValue
),再钳位后传给
FogAnalog()
。
硬件协同要点
:
-
DHT22 的 VCC/GND 必须与 Programming Fog 板共地,但信号线(DATA)需独立连接至 Arduino 数字引脚,
绝不可与 A0 复用
; - 电位器中心抽头接 A0,两端分别接 5V 和 GND,构成标准分压电路。
4.2 艺术互动雾墙(手势/声音触发)
系统构成
:Programming Fog 板 + Arduino Mega2560 + GP2Y0A21YK0F 红外测距传感器 + MAX4466 麦克风放大模块
交互逻辑
:
-
红外传感器检测人体距离
< 50cm
→ 触发
FogOn()
启动; -
麦克风采集环境音量 RMS 值 → 映射为
0–1023
→ 输入
FogAnalog()
控制雾量(声音越大,雾越浓); -
距离
> 100cm
且静音持续 5 秒 → 自动
FogOff()
。
关键时序考量
:
-
FogOn()
与
FogAnalog()
的调用间隔应
> 100ms
,避免高频开关冲击雾化片寿命; -
麦克风 RMS 计算需在
loop()
中高效完成(推荐使用
analogRead()
采样 + 滑动窗口方差算法)。
5.1 常见问题诊断表
FogOn()
无反应
2. GND 未共地
3. 雾化器损坏
FogAnalog()
雾量不随 A0 变化
2. 电位器接触不良
3.
inputValue
超出 0–1023
Serial.println(analogRead(A0))
直接验证;测量 A0 对地电压是否 0–5V 线性变化;添加
constrain()
2. 地线阻抗过大
5.2 工程级可靠性加固建议
-
电源去耦
:在 Programming Fog 板 VCC 引脚就近焊接
0.1μF
陶瓷电容 +
10μF
电解电容,抑制高频噪声; -
A0 输入保护
:在 A0 与 Arduino 引脚间串联
1kΩ
限流电阻,并对地并联
5.1V
TVS 二极管,防止静电或浪涌损坏 ADC; -
雾化器寿命管理
:在
loop()
中累计运行时间,当
totalRunTime > 3600000
(1 小时)时强制
FogOff()
并
Serial.println("Fog paused for cooling")
,避免超声波片过热失效。
尽管 Programming Fog 库原生基于 Arduino,但其设计理念可无缝迁移到更广泛的嵌入式平台:
-
STM32 HAL 移植
:将
FogInit()
映射为
HAL_GPIO_Init()
+
HAL_ADC_Start()
;
FogOn()
/
FogOff()
映射为
HAL_GPIO_WritePin()
;
FogAnalog()
映射为
HAL_TIM_PWM_Start()
+
__HAL_TIM_SET_COMPARE()
。关键在于复用其“使能+模拟量”双控范式。 -
FreeRTOS 任务封装
:如前文示例,将雾化控制封装为独立任务,通过
QueueHandle_t
接收来自传感器任务的
uint16_t
雾量指令,实现模块化解耦。 -
与 LVGL 图形库联动
:在 STM32 + LCD 屏幕项目中,用 LVGL 滑块控件 (
lv_slider
) 的事件回调函数获取
0–100
值,经
map(value, 0, 100, 0, 1023)
后传入
FogAnalog()
,实现直观的图形化雾量调节界面。
Programming Fog 库的价值,远不止于控制一片雾化片。它代表了一种
面向物理世界交互的嵌入式抽象哲学
:将复杂的机电系统(高压、高湿、非线性)封装为几个语义清晰、行为确定的函数。这种“硬件即 API”的思想,正是现代 IoT 设备开发的核心——开发者无需深究超声波振子的谐振频率、MOSFET 的开关损耗,只需理解
FogOn()
意味着“此刻开始吐雾”,
FogAnalog(512)
意味着“一半浓度”。
在实际项目中,我曾用此库在 2 小时内完成一个博物馆展品的雾效升级:将原有机械定时器替换为 Arduino + Programming Fog 板 + 红外感应模块。代码仅 37 行,却实现了“观众靠近即起雾,离开 3 秒后渐隐”的自然交互。其成功的关键,正是库所承诺的
确定性行为
——
FogOff()
调用后,雾必然在 0.5 秒内消散,这种可预测性,是任何未经充分验证的 DIY 驱动方案都无法提供的工程保障。











