안녕하세요! 오늘은 보이지 않는 힘, ‘자기장’을 감지해서 실시간 데이터로 바꿔주는 신기한 부품, **SS49E 홀 센서(Hall Effect Sensor)**에 대해 깊이 있게 알아보겠습니다.
최근 쇼츠 영상에서 보여드린 것처럼, 이 작은 부품 하나로 고속 회전하는 바퀴의 RPM을 측정할 수 있는데요. 그 원리와 구현 과정에서 겪었던 노하우를 모두 공유합니다.

1. 홀 센서(SS49E)란 무엇인가?
홀 센서는 **’홀 효과(Hall Effect)’**를 이용해 자기장의 세기를 전압 신호로 바꾸는 센서입니다.
- 리니어(Linear) 출력: SS49E는 ‘리니어’ 타입입니다. 단순히 자석이 “있다/없다”만 알려주는 게 아니라, 자석이 얼마나 가까운지, 어느 극(N/S)인지에 따라 전압을 연속적으로 출력합니다.
- 작동 원리: 자석의 N극이 가까워지면 기준 전압보다 값이 커지고, S극이 가까워지면 값이 작아지는 특성을 가집니다. (또는 그 반대)
2. 리드 스위치(Reed Switch)와는 무엇이 다른가?
자석에 반응한다는 점 때문에 리드 스위치와 헷갈려 하시는 분들이 많습니다. 하지만 결정적인 차이가 있습니다.
| 특징 | 리드 스위치 (Reed Switch) | 홀 센서 (SS49E) |
| 작동 방식 | 물리적인 금속 접점이 자석에 의해 붙음 | 반도체 소자가 자기장을 전기 신호로 변환 |
| 수명 | 물리적 접점이므로 수명에 한계가 있음 | 반도체식이므로 반영구적임 |
| 반응 속도 | 느림 (기계적 움직임 필요) | 매우 빠름 (고속 회전 측정 가능) |
| 정밀도 | On/Off만 가능 | 자기장의 세기를 숫자로 측정 가능 |
결론: 고속으로 돌아가는 5,000 RPM 이상의 바퀴를 측정하려면, 물리적 접점이 없는 홀 센서가 필수입니다.
3. RPM 측정의 핵심 로직 (자석 2개의 마법)
이번 프로젝트에서는 바퀴에 자석을 2개 달았습니다. 왜일까요?
바퀴의 무게 균형(Balance)을 맞추기 위해서이기도 하지만, 더 정밀한 측정이 가능하기 때문입니다.
- 계산 공식: 자석이 2개라면, 센서에 신호가 2번 들어와야 한 바퀴를 돈 것입니다.
- 따라서 신호와 신호 사이의 시간(
duration)을 측정했다면, RPM 공식은 다음과 같습니다.$$RPM = \frac{60,000,000}{\text{duration\_us} \times 2} = \frac{30,000,000}{\text{duration\_us}}$$
4. 실전 문제 해결: “자석이 없는데 왜 RPM이 나오죠?”
개발 과정에서 가장 당황스러웠던 점은 자석이 가만히 있는데도 RPM이 300~400씩 찍히는 현상이었습니다. 원인은 바로 **전기적 노이즈(Noise)**였습니다.
- 스파이크 노이즈: 눈에는 보이지 않지만, 전압이 찰나의 순간에 튀면서 코드가 이를 자석으로 오해합니다.
- 해결책 (Hysteresis): 기준값(2318)에서 아주 미세하게 변하는 것은 무시하고, 확실하게 값이 튈 때(예: 차이가 500 이상)만 자석으로 인식하도록 **문턱값(Hysteresis)**을 설정해야 합니다.
- 시간 제한: 5,000 RPM의 물리적 한계 시간을 계산해, 그보다 너무 빠르게 들어오는 신호는 노이즈로 간주하고 버리는 로직을 추가했습니다.
5. 최종 보정 코드 (MicroPython)
ESP32-C3와 SS49E를 연결했을 때 가장 안정적으로 작동하는 코드 구조입니다.
Python
# 핵심 로직 요약
diff_from_center = abs(raw_val - CENTER_VAL)
if not counting_state and diff_from_center > HYSTERESIS:
duration_us = time.ticks_diff(current_time_us, last_trigger_time)
if duration_us > 5000: # 5000us 이하는 노이즈로 간주 (고속 측정 가능)
raw_rpm = 30000000 / duration_us
# 이동 평균 필터로 값 안정화
...
6. 응용 및 다음 단계: 가전제품 전원 감지?
홀 센서의 활용도는 무궁무진합니다.
SS49E는 워낙 예민해서, 전선에 흐르는 전류가 만드는 미세한 자기장도 읽어낼 수 있습니다.
- 다음 프로젝트 예고: 가전제품 전선 근처에 홀 센서를 대면, 제품이 켜졌는지 꺼졌는지 비접촉으로 확인할 수 있을까요? 전류가 흐를 때 생기는 자기장의 변화를 포착하는 실험을 다음 포스팅에서 다뤄보겠습니다.

Python ss49e.py
from machine import ADC, Pin
import time
# 1. 하드웨어 설정
hall_sensor = ADC(Pin(0))
hall_sensor.atten(ADC.ATTN_11DB)
CENTER_VAL = 2318
# 노이즈가 350까지 튀었으므로, 확실하게 600으로 높여서 자석만 잡습니다.
HYSTERESIS = 450
OUTPUT_INTERVAL = 200
# 2. 변수 초기화
last_trigger_time = time.ticks_us()
last_output_time = time.ticks_ms()
counting_state = False
filtered_rpm = 0
rpm_history = [0] * 5
print("Center_Line,Raw,Actual_RPM")
while True:
current_time_ms = time.ticks_ms()
current_time_us = time.ticks_us()
raw_val = hall_sensor.read()
diff_from_center = abs(raw_val - CENTER_VAL)
# --- [5000 RPM 대응 로직] ---
if not counting_state and diff_from_center > HYSTERESIS:
duration_us = time.ticks_diff(current_time_us, last_trigger_time)
# 5000 RPM일 때 간격이 6000us이므로, 5000us까지는 허용합니다.
# (약 6000 RPM까지 측정 가능해짐)
if duration_us > 5000:
raw_rpm = 30000000 / duration_us
rpm_history.pop(0)
rpm_history.append(raw_rpm)
filtered_rpm = sum(rpm_history) / len(rpm_history)
last_trigger_time = current_time_us
counting_state = True
elif counting_state and diff_from_center < (HYSTERESIS * 0.7):
counting_state = False
# 정지 판단 시간 (0.5초로 단축하여 반응성 향상)
if time.ticks_diff(current_time_us, last_trigger_time) > 500000:
rpm_history = [0] * 5
filtered_rpm = 0
# --- [플로터 출력] ---
if time.ticks_diff(current_time_ms, last_output_time) >= OUTPUT_INTERVAL:
print(f"{CENTER_VAL},DATA: {raw_val}, RPM: {int(filtered_rpm)}")
last_output_time = current_time_ms
# 샘플링 속도를 높이기 위해 대기 시간을 최소화
time.sleep_us(10)



답글 남기기