YF-S401 유량 센서로 물의 흐름 재기 — 커피 머신은 물을 어떻게 정량으로 넣을까

고장 난 네스프레소 캡슐 머신을 버리기 전에 분해해 본 적이 있습니다. 펌프, 히터까지는 이름을 맞힐 수 있었는데, 물길 중간에 끼어 있는 엄지손가락만 한 부품 하나는 정체를 알 수 없었습니다. 한참을 들여다보고 찾아보니 그것은 유량계(flow meter) — 커피 한 잔에 들어갈 물을 정량으로 공급하기 위해, 지나가는 물의 양을 세고 있는 부품이었습니다. 캡슐 머신이 에스프레소 40 mL, 룽고 110 mL 를 매번 정확히 맞추는 비결이 여기에 있었던 것이지요. 이런 부품을 취미용으로도 구할 수 있는지 찾다가 만난 것이 이 실험의 주인공 YF-S401 입니다.

이 실험에서는 YF-S401 을 아두이노에 연결해 물의 유량(단위 시간당 흐르는 부피)을 재고, 유량을 시간에 대해 쌓아서(적분해서) 커피 머신처럼 원하는 부피만큼 물을 세어 봅니다.

원리 — 회전수로 유량을 재고, 세어서 부피를 얻는다

YF-S401 은 물길에 놓인 작은 바람개비(터빈) 의 회전을 홀 센서로 세는 센서입니다. 터빈이 한 바퀴 도는 동안 지나가는 물의 부피가 거의 일정해서, 물 1 리터가 지나가면 펄스 5880 개가 나옵니다(데이터시트의 f = 98\,Q 를 환산한 값). 즉 펄스 하나가 물 약 0.17 mL 입니다. 그래서 이 센서가 근본적으로 재는 것은 부피입니다: 유량이 요동쳐도 펄스 수를 세면 지나간 부피가 그대로 나옵니다. 유량 Q 는 파생량으로, 단위 시간당 펄스 수(진동수 f)를 재면 됩니다. 커피 머신이 물을 정량으로 넣는 비결이 이 한 줄입니다.

센서 내부가 어떻게 생겼는지(회전축에 박힌 반은 N극·반은 S극인 자석과 홀 센서), 그리고 왜 한 바퀴당 부피가 일정하고 펄스 세기가 곧 부피 측정이 되는지는 YF-S401 부품 노트에서 분해 사진과 함께 자세히 다룹니다.

준비물

  • YF-S401 유량 센서 (6 mm 호스용, 측정 범위 0.3~6 L/min)
  • 아두이노 우노 (호환 보드 가능)
  • 내경 6 mm 실리콘 또는 비닐 호스 1 m 정도
  • 물통 2개 (공급용, 받이용), 계량컵
  • 점퍼선 (암-수 3가닥)
  • (선택) 지난 실험에서 만든 전자저울 — 계량컵 대신 부피를 정밀하게 재는 데 쓴다 (아래 "저울로 부피 재기" 절 참고)

물은 펌프 없이 높이 차이로 흘리면 됩니다. 공급 물통을 책상 위에, 센서와 받이 물통을 아래에 두면 충분한 유량이 나옵니다.

<!-- TODO: parts.jpg — YF-S401 실물 사진 (분해한 네스프레소 유량계와 나란히 찍으면 최고) -->

배선

선이 3가닥뿐이라 배선은 간단합니다.

YF-S401 아두이노
빨강 5V
검정 GND
노랑 (신호) D2

신호선을 D2 에 연결하는 이유가 있습니다. 펄스가 초당 수백 번 나오기 때문에 loop() 에서 한가하게 읽다가는 놓칩니다. 그래서 인터럽트(interrupt) — 신호가 바뀌는 순간마다 하던 일을 멈추고 개수를 세는 방식 — 를 쓰는데, 우노에서 인터럽트가 되는 핀이 D2, D3 입니다.

센서 몸통의 화살표가 물이 흐르는 방향과 같도록 호스를 연결합니다.

<!-- TODO: wiring.png — Fritzing 배선도 (YF-S401 부품은 fzpz 필요할 수 있음) -->

아두이노 코드

라이브러리 없이 인터럽트로 펄스를 직접 셉니다. 원리 그대로, 펄스 수 → 부피가 기본이고 유량은 "1초 동안 늘어난 부피"로 파생시킵니다. 보정 상수도 유량이 아니라 리터당 펄스 수 하나입니다.

const int SIG_PIN = 2;

// 보정 상수: 1 리터당 펄스 수 — 데이터시트 값. '보정' 단계에서 직접 잰 값으로 바꿀 것
float PULSES_PER_LITER = 5880.0;

volatile unsigned long pulses = 0;      // 1초 구간의 펄스 수
unsigned long totalPulses = 0;          // 누적 펄스 수 = 부피의 원본

void countPulse() { pulses++; }

void setup() {
  Serial.begin(9600);
  pinMode(SIG_PIN, INPUT_PULLUP);
  attachInterrupt(digitalPinToInterrupt(SIG_PIN), countPulse, RISING);
  Serial.println("volume[mL]\tflow[L/min]");
}

void loop() {
  delay(1000);

  noInterrupts();                // 세는 도중 값이 바뀌지 않게 잠깐 멈춤
  unsigned long n = pulses;
  pulses = 0;
  interrupts();

  totalPulses += n;

  // 부피가 기본: 펄스 수 / (리터당 펄스 수)
  float volume = totalPulses / PULSES_PER_LITER * 1000.0;   // 누적 mL
  // 유량은 파생: 1초 동안 지나간 부피(L) x 60 = L/min
  float flow = n / PULSES_PER_LITER * 60.0;

  Serial.print(volume, 1);
  Serial.print("\t");
  Serial.println(flow, 2);
}

1초마다 누적 부피(mL)와 순간 유량(L/min)이 출력됩니다.

값이 튄다면 — 지터(jitter) 대책

물이 멈췄는데 부피가 슬금슬금 늘거나 유량 표시가 이상하게 떨린다면 지터를 의심해 봅시다. 원인은 두 갈래입니다.

기계적 지터 — 터빈이 진동·출렁임으로 까딱거리며 내는 가짜 펄스. 홀 센서는 회전 방향을 모르기 때문에 생기는 문제로, 부품 노트의 지터 항목에서 설명합니다.

전기적 지터 — 센서 출력 자체는 홀 IC 가 만들어 주는 디지털 신호라 보통 깨끗하지만, 신호선이 길면 안테나처럼 잡음을 주워 담고 신호의 오르내림도 무뎌집니다. 신호가 문턱 전압 근처에서 어물거리면 인터럽트가 한 번의 엣지를 여러 번으로 세어 버립니다. 이런 어물거림을 잘라 내는 회로가 슈미트 트리거(Schmitt trigger) — 올라갈 때와 내려갈 때의 문턱을 다르게 두는(히스테리시스) 입력단입니다.

  • 아두이노(AVR)의 입력 핀에도 슈미트 특성이 있긴 하지만 히스테리시스 폭이 작고 데이터시트에 값이 명시되어 있지 않아, 크게 기대하기는 어렵습니다.
  • 잡음이 실제로 문제라면: 신호선을 짧게 하고, 신호선–GND 사이에 작은 RC 필터를 넣거나, 슈미트 트리거 로직 칩(74HC14, 74HC132, CD40106)을 하나 거쳐 아두이노에 넣으면 확실합니다. 소프트웨어로는 "마지막 펄스로부터 일정 시간 안에 온 펄스는 무시"하는 필터도 간단하고 효과적입니다.
  • STM32 계열 보드를 쓴다면 사정이 좋습니다: 모든 GPIO 가 히스테리시스가 보장되는 슈미트 입력인 데다, 타이머 입력에는 설정 가능한 디지털 필터(짧은 글리치 무시)가 있고, 펄스 카운트 자체를 CPU 개입 없이 타이머 하드웨어로 셀 수도 있습니다.

슈미트 트리거 칩 번호 메모. 대표 번호는 74HC14 — 슈미트 트리거 인버터 6개가 든 헥스 인버터이고, TTL 시절의 원조는 7414 입니다. 같은 계열로 CMOS 4000 시리즈의 CD40106(헥스 슈미트 인버터), 슈미트 입력 NAND 4개짜리 74HC132 도 있습니다. 어느 것이든 신호 정형(어물거리는 엣지를 칼같이 세우는 일)에는 동등하니, 요즘 구하기 쉽고 5 V 아두이노와 궁합이 좋은 74HC14 를 쓰면 됩니다. 한 가지 유의: 74HC14/40106 은 인버터라 신호가 뒤집혀 나옵니다. 게이트 두 단을 직렬로 거치거나, 코드의 attachInterrupt 에서 RISINGFALLING 으로 바꾸면 해결됩니다. 채널이 하나만 필요하면 SOT-23 낱개 패키지인 74LVC1G14(반전)·74LVC1G17(비반전 버퍼)도 있습니다.

보정 — 계량컵으로 나만의 "리터당 펄스 수" 구하기

데이터시트의 5880 펄스/L 는 대표값일 뿐이고, 개체 차이와 설치 조건(호스 굵기, 꺾임)에 따라 몇 % 씩 다릅니다. 커피 머신처럼 정량을 맞추려면 직접 보정해야 합니다. 다행히 보정 상수가 "리터당 펄스 수" 그 자체라서, 재서 나누면 끝입니다.

  1. 누적 펄스 수를 0으로 만들고(리셋 버튼), 물을 흘려 받이 컵에 받습니다.
  2. 물을 멈춘 뒤 누적 펄스 수 N 을 기록하고, 받은 물의 부피 V 를 계량컵으로 잽니다.
    • 더 정밀하게 재는 방법이 다음 절에 있습니다 — 전자저울과 "물 1 L ≈ 1 kg".
  3. N/V (V 는 리터 단위) 가 곧 나만의 보정 상수입니다. 코드의 PULSES_PER_LITER 를 이 값으로 바꿉니다.
  4. 부피를 바꿔 가며 2~3회 반복해 값이 일정한지 확인합니다.

저울로 부피 재기 — 물 1 L 는 왜 1 kg 인가

보정의 정밀도는 결국 "받은 물의 부피 V 를 얼마나 정확히 재느냐"에서 결정됩니다. 계량컵은 눈금을 잘 읽어도 몇 % 오차가 나기 쉽습니다. 그런데 지난 실험에서 만든 전자저울이 있다면 부피를 훨씬 정확히 잴 수 있습니다. 물은 1 g 이 곧 1 mL 이기 때문입니다.

이것은 우연이 아니라 미터법의 설계입니다. 킬로그램이라는 단위가 애초에 "물 1 리터(4 ℃)의 질량"으로 정의되었기 때문에, 물의 밀도는 정의상 1 kg/L 로 맞춰져 있었습니다. 지금은 킬로그램의 정의가 바뀌었지만 값은 그대로라, 상온(20 ℃)의 물도 밀도가 0.998 g/mL — 1 g = 1 mL 로 계산해도 오차 0.2 % 수준입니다. 계량컵보다 한 자릿수 이상 정확합니다. (물 1 리터가 금고 속 금속 원기를 거쳐 플랑크 상수가 되기까지, 킬로그램 정의의 뒷이야기는 1 kg 은 어떻게 정해졌나에서 다룹니다.)

절차는 간단합니다.

  1. 받이 컵을 저울에 올리고 0점을 잡습니다(tare).
  2. 보정 절차대로 물을 받고, 저울이 표시하는 질량 m (g) 을 읽습니다. 그러면 V = m mL.
  3. 더 꼼꼼히 하려면 물의 온도를 재서 밀도로 나눕니다: V = m/\rho (\rho 는 20 ℃에서 0.998, 25 ℃에서 0.997 g/mL).

지난 실험에서 만든 저울이 이번 실험의 측정 기구가 되는 셈입니다. 분동이 저울을 보정했고, 그 저울이 유량계를 보정합니다. 모든 측정기는 이렇게 자기보다 더 믿을 만한 기준에 기대어 눈금을 얻습니다.

측정해 보기

  • 정량 공급 재현하기 — 목표 40 mL (에스프레소 한 잔)에 해당하는 펄스 수를 계산하고, 누적 부피가 그 값에 도달하면 Serial 에 "STOP" 을 출력하게 코드를 고쳐 봅시다. 출력을 보고 손으로 물을 잠갔을 때 실제로 몇 mL 받아졌는지 확인해 보세요. (진짜 커피 머신은 이 신호로 펌프를 끕니다.)
  • 유량-높이 관계 — 공급 물통의 높이를 바꿔 가며 유량을 기록해 봅시다. 높이가 2배면 유량도 2배가 될까요?
  • 측정 한계 확인 — 물을 아주 조금씩 흘리면 어느 유량 아래에서 바람개비가 서 버리는지(측정 하한 0.3 L/min) 확인해 봅시다.

<!-- TODO: graph.svg — 유량 vs 물통 높이, 또는 보정 직선 그래프 -->

생각해 볼 것

  1. 펄스 진동수(유량)를 재는 것과 펄스 개수(부피)를 세는 것 — 수학으로 말하면 두 양은 어떤 관계인가? 속도와 이동 거리의 관계와 비교해 보자.
  2. 물통의 수위가 내려가면 유량도 서서히 줄어든다. 그래도 누적 펄스 수로 잰 부피는 정확한 이유가 무엇인가? 속도가 수시로 변하는 자동차에서도 주행거리계(바퀴 회전수 세기)는 정확한 것과 비교해 보자. 반대로 처음에 잰 유량에 시간을 곱해 V = Q \times t 로 계산했다면 어떻게 됐을까? (속도계 숫자에 시간을 곱해 거리를 구하는 셈이다.)
  3. 아주 작은 유량에서는 바람개비가 마찰 때문에 돌지 않아 측정값이 0 이 된다. 이 오차는 보정으로 없앨 수 있는 종류인가, 없는 종류인가?
  4. 뜨거운 물을 흘리면 측정에 어떤 영향이 있을까? (부피는 온도에 따라 변한다 — 커피 머신 설계자의 고민이기도 하다.)

더 해 보기

  • 받이 물통을 전자저울 위에 올려 두고, 유량계의 누적 부피와 저울의 질량 증가를 동시에 기록해 두 측정을 교차 검증해 보기.
  • 공급 물통 수위 h 와 유량의 관계 재 보기 — 토리첼리 정리대로 Q \propto \sqrt{h} 일까, 호스의 저항 때문에 Q \propto h 일까? 좋은 주제라 별도 실험 글로 다룹니다.
  • 릴레이와 소형 펌프를 추가해 목표 부피에서 자동으로 멈추는 진짜 정량 공급 장치 만들기 — 캡슐 머신의 물 공급부를 그대로 재현하는 셈이다.