You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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:溢流问题的修复方案

溢流原因

  1. 变量未重置:完成一次出水后,flow_frequency、vol等变量没有清零,下次触发时直接跳过停止逻辑;
  2. 阻塞式循环:while循环会阻塞整个程序,导致水流过程中无法响应按钮输入,且中断可能被干扰;
  3. 按钮无消抖:机械按钮的抖动会导致误触发,引发重复执行出水逻辑;
  4. 逻辑顺序错误:代码中在按钮触发后直接开电磁阀,没有判断是否已经达到目标容量。

修改后的代码

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);
    }
  }
}

代码修改说明

  1. 正确采集脉冲:用flow_count在中断里累加实际传感器脉冲,不再手动自增;
  2. 非阻塞逻辑:去掉阻塞的while循环,用状态变量is_watering管理出水过程,不影响按钮和中断响应;
  3. 按钮消抖:加入消抖延迟,避免机械抖动误触发;
  4. 变量重置:每次开始出水时重置flow_count,确保每次从零开始计数;
  5. 明确状态管理:用is_watering标记是否正在出水,避免重复触发;
  6. 简化脉冲计算:直接用规格书给出的脉冲系数计算目标脉冲数,无需复杂转换。

内容的提问来源于stack exchange,提问作者Lord Voldemort

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.16 19:01:23