Flow Sensor控制设备脉冲计数偏差及重复触发溢流问题咨询
问题1:脉冲数计算与实际不符的原因分析
核心原因:代码逻辑完全错误,未正确采集传感器脉冲
你的代码存在致命逻辑问题:在1秒周期的判断块中,先重置了flow_frequency,随后在while(flow_frequency<=1910)循环里手动自增flow_frequency——这完全没有用到流量传感器的中断计数,相当于靠软件循环瞎数,自然和实际需要的脉冲数差了好几倍。
其他可能的辅助因素
- 公式转换误差:按YF-S201的规格,脉冲频率
Hz=7.5*Q(Q单位L/min)。600L/H换算为10L/min,每秒脉冲数是75。750ml的总脉冲数应为75 * (0.75L / 10L/min * 60s/min) = 337.5,和你说的369接近,可能是你计算时的单位转换误差,但这不是主要问题。 - 电磁阀反向磁通的影响:反向磁通本身不会直接影响传感器读数,但电磁阀工作时的电磁干扰可能导致传感器脉冲信号出现杂波,引发中断误触发/漏触发。但你的情况是数值差了5倍以上,显然代码逻辑错误才是主因。
问题2:溢流问题的修复方案
溢流原因
- 变量未重置:完成一次出水后,
flow_frequency、vol等变量没有清零,下次触发时直接跳过停止逻辑; - 阻塞式循环:
while循环会阻塞整个程序,导致水流过程中无法响应按钮输入,且中断可能被干扰; - 按钮无消抖:机械按钮的抖动会导致误触发,引发重复执行出水逻辑;
- 逻辑顺序错误:代码中在按钮触发后直接开电磁阀,没有判断是否已经达到目标容量。
修改后的代码
volatile unsigned long flow_count = 0; // 用unsigned long避免溢出 const int flowsensor = 10; const int SolenoidPumpPin = 11; const int buttonPin = 12; // 出水参数 const float TARGET_VOLUME = 0.75; // 目标容量750ml=0.75L const float PULSE_PER_LITER = 450; // YF-S201的脉冲系数:7.5脉冲/L/min *60s=450脉冲/L unsigned long target_pulses = TARGET_VOLUME * PULSE_PER_LITER; // 状态变量 bool is_watering = false; unsigned long last_button_press = 0; const unsigned long DEBOUNCE_DELAY = 50; // 按钮消抖延迟 void flow_interrupt() { flow_count++; } void setup() { pinMode(SolenoidPumpPin, OUTPUT); digitalWrite(SolenoidPumpPin, HIGH); // 初始关闭电磁阀 pinMode(flowsensor, INPUT_PULLUP); // 启用内部上拉电阻 pinMode(buttonPin, INPUT_PULLUP); // 避免按钮引脚悬空 attachInterrupt(digitalPinToInterrupt(flowsensor), flow_interrupt, RISING); Serial.begin(9600); } void loop() { // 按钮消抖处理 int button_state = digitalRead(buttonPin); if (button_state == LOW && millis() - last_button_press > DEBOUNCE_DELAY) { last_button_press = millis(); if (!is_watering) { // 开始出水:重置计数,打开电磁阀 flow_count = 0; is_watering = true; digitalWrite(SolenoidPumpPin, LOW); // 打开电磁阀(根据硬件接线调整电平) Serial.println("开始出水"); } else { // 强制停止出水 is_watering = false; digitalWrite(SolenoidPumpPin, HIGH); Serial.println("强制停止"); } } // 非阻塞式判断是否达到目标容量 if (is_watering) { if (flow_count >= target_pulses) { is_watering = false; digitalWrite(SolenoidPumpPin, HIGH); Serial.print("完成出水,实际脉冲数:"); Serial.println(flow_count); } } }
代码修改说明
- 正确采集脉冲:用
flow_count在中断里累加实际传感器脉冲,不再手动自增; - 非阻塞逻辑:去掉阻塞的
while循环,用状态变量is_watering管理出水过程,不影响按钮和中断响应; - 按钮消抖:加入消抖延迟,避免机械抖动误触发;
- 变量重置:每次开始出水时重置
flow_count,确保每次从零开始计数; - 明确状态管理:用
is_watering标记是否正在出水,避免重复触发; - 简化脉冲计算:直接用规格书给出的脉冲系数计算目标脉冲数,无需复杂转换。
内容的提问来源于stack exchange,提问作者Lord Voldemort
相关产品推荐
相关产品推荐

