ESP8266 IR 슬롯형 광학 속도 센서
이 튜토리얼에서는 ESP8266 NodeMCU와 IR 슬롯형 광학 속도 센서를 사용하는 방법을 알아봅니다. 센서의 좁은 틈을 무언가가 지나갈 때마다 보드가 그것을 알 수 있습니다. 이 신호 하나로 NodeMCU는 물체의 수를 세거나 모터가 얼마나 빨리 도는지 알 수 있습니다. 자세히 다음 내용을 배웁니다:
- 센서 안의 빛 게이트(옵토 인터럽터 또는 포토 인터럽터로도 판매됨)가 HIGH 또는 LOW 신호를 내는 원리
- 센서를 NodeMCU의 3.3V 핀과 D5(GPIO14) 핀에 연결하는 방법, 그리고 비워 두어야 할 핀
- 슬롯을 막는 물체를 모두 세는 ESP8266 코드를 작성하는 방법
- 인코더 디스크와 IRAM_ATTR이 붙은 인터럽트 함수로 모터 속도를 RPM(분당 회전수)으로 측정하는 ESP8266 코드를 작성하는 방법
다음을 권장합니다:
- 사람이 손으로 노브를 돌리고 코드가 왼쪽인지 오른쪽인지 알아야 한다면 ESP8266 - 로터리 엔코더를 사용하세요.
- 찾으려는 물체가 센서 앞 몇 센티미터 거리에 있고 작은 슬롯을 통과할 수 없다면 ESP8266 - 장애물 센서를 사용하세요.

준비물
| 1 | × | Micro USB Cable | 아마존 | |
| 1 | × | ESP8266 NodeMCU | 쿠팡 | 아마존 | |
| 1 | × | USB 케이블 타입-A to 타입-C (USB-A PC용) | 쿠팡 | 아마존 | |
| 1 | × | USB 케이블 타입-C to 타입-C (USB-C PC용) | 아마존 | |
| 1 | × | IR Slotted Optical Speed Sensor | 아마존 | |
| 1 | × | 점퍼케이블 | 쿠팡 | 아마존 | |
| 1 | × | (옵션) Breadboard | 쿠팡 | 아마존 | |
| 1 | × | (추천) ESP8266용 스크루 터미널 확장 보드 | 쿠팡 | 아마존 |
IR 슬롯형 광학 속도 센서에 대하여
검은 플라스틱으로 만든 작은 문틀을 떠올려 보세요. 보이지 않는 빔이 문틀을 가로지릅니다. 단단한 무언가가 문틀을 통과하면 빔이 끊기고, 센서는 즉시 ESP8266에 알려 줍니다. 이 모듈이 하는 일은 이것이 전부이지만, 빠르고 아주 깨끗한 신호로 해냅니다. 그래서 속도 센서, 펄스 카운터, 엔드 스톱으로 많이 쓰입니다.
U자형 몸체 내부

모듈은 세 가지 부품으로 구성됩니다:
- 한쪽 팔에 있는 적외선 LED. 항상 IR 빛을 내보냅니다.
- 반대쪽 팔에 있는 NPN 포토트랜지스터. 5.9 mm 떨어져서 LED를 마주 봅니다.
- 작은 기판 위의 슈미트 트리거. 포토트랜지스터 신호를 또렷한 디지털 레벨로 바꿉니다.
OUT 핀은 빔을 따라갑니다:
- 빔이 포토트랜지스터에 도달함(슬롯이 비어 있음): OUT은 HIGH.
- 단단한 물체(카드, 손가락, 인코더 디스크의 이빨)가 빔을 끊음: OUT은 LOW.
슈미트 트리거 덕분에 신호 가장자리에 지터가 없습니다. ESP8266 코드는 디바운스 단계 없이 값을 그대로 사용할 수 있습니다.
테스트하기 전에 알아 둘 몇 가지 팁:
- 반대편이 보이지 않는 물체를 사용하세요. 투명한 플라스틱은 IR 빛이 통과할 수 있어 센서가 알아채지 못할 수 있습니다.
- 다른 제조사의 일부 모듈은 반대 로직(비어 있을 때 LOW)을 가집니다. 이 경우 카운팅 코드에서 LOW와 HIGH를 서로 바꾸세요. RPM 코드는 슬롯마다 한쪽 에지만 세므로 그대로 올바른 속도를 줍니다.
사양
| IR 슬롯형 광학 속도 센서 | |
|---|---|
| 센서 종류 | 슬롯형 광전 센서(IR LED + NPN 포토트랜지스터) |
| 슬롯 폭 | 5.9 mm |
| 동작 전압 | 3.3V ~ 5V DC |
| 출력 | 디지털(TTL), 막히면 LOW, 비어 있으면 HIGH |
| 신호 처리 | 내장 슈미트 트리거 |
| 고정 방식 | 양 끝에 M3 나사 구멍 |
| 핀 | 3개(VCC, GND, OUT) |
두 개의 M3 구멍으로 모듈을 로봇 섀시나 모터 브래킷에 나사로 고정할 수 있으므로, 디스크가 옆에서 도는 동안에도 센서는 같은 자리에 있습니다. 대표적인 용도: 작은 모터의 RPM 측정기, 로봇 자동차의 바퀴 속도 피드백, 움직이는 벨트 위 물품 카운터, 바퀴 회전수를 세는 거리 측정기, 비접촉 리밋 또는 위치 스위치.
IR 슬롯형 광학 속도 센서 핀배열

- VCC 핀: NodeMCU의 3V3 핀에 연결해야 합니다(5V나 VIN에는 연결하지 마세요)
- GND 핀: NodeMCU의 G(GND) 핀(0V)에 연결해야 합니다
- OUT 핀: 디지털 출력이며, NodeMCU의 입력 핀(이 튜토리얼에서는 D5)에 연결해야 합니다
※ 주의:
모듈의 핀 배열은 제조사마다 다를 수 있으며, 같은 제품이라도 생산 로트에 따라 다를 수 있습니다. 모듈을 사용할 때는 항상 모듈에 인쇄된 라벨을 확인해야 합니다. 꼼꼼히 살펴보세요!
왜 5V가 아니라 3.3V일까요? OUT 핀은 VCC에 걸린 전압만큼까지 올라갑니다. ESP8266은 3.3V 칩입니다. 센서에 5V를 주면 OUT도 NodeMCU 핀에 5V를 보내게 됩니다. VCC를 3V3 핀에서 받으면 OUT은 0V~3.3V 사이에 머물러 보드에 안전합니다.
인코더 디스크: 펄스에서 RPM으로
인코더 디스크는 가장자리 근처에 구멍이 한 줄로 나 있는 평평한 바퀴입니다. 이것을 모터 축이나 바퀴에 끼우고, 디스크의 가장자리가 슬롯을 통과하도록 센서를 놓습니다. 디스크가 돌면 구멍과 이빨이 차례로 빔을 지나갑니다. 이빨 하나마다 OUT이 한 번 LOW가 됩니다.
대부분의 TT 기어 모터 키트에는 20슬롯 디스크가 들어 있습니다. ESP8266이 펄스를 속도로 바꾸는 방법은 다음과 같습니다:
- 1초 동안 펄스를 셉니다.
- 60을 곱해 분당 펄스 수를 구합니다.
- 20(한 바퀴의 펄스 수)으로 나누어 분당 회전수, 즉 RPM을 구합니다.
배선도
점퍼 와이어 세 개를 사용합니다: 센서 VCC는 NodeMCU의 3V3 핀에, 센서 GND는 G 핀에, 센서 OUT은 D5에 연결합니다. 아래 이미지를 참고하세요.

이 이미지는 Fritzing을 사용하여 만들어졌습니다. 이미지를 확대하려면 클릭하세요.
ESP8266 핀배열 및 ESP8266 전원을 켜는 방법에 대해 더 많이 보십시오.
D5 라벨 또는 GPIO14?
NodeMCU의 실크 스크린에는 D1, D2, D5 같은 라벨이 표시되어 있습니다. ESP8266 칩 자체는 GPIO 번호를 사용하며, 둘은 서로 같지 않습니다. 보드의 D5는 칩에서 GPIO14입니다. 코드에서는 D5라고 쓰면 Arduino IDE용 ESP8266 코어가 GPIO14로 바꿔 줍니다. 그냥 5라고 쓰면 코드는 D1 핀인 GPIO5를 사용합니다. 흔한 실수이므로 코드에 항상 "D"를 붙이세요.
D5를 이미 사용 중이라면 OUT 선을 다른 핀으로 옮겨도 됩니다. 다음 목록으로 선택하세요:
| NodeMCU 라벨 | GPIO | 이 센서에 적합한가요? |
|---|---|---|
| D1 | GPIO5 | 예 |
| D2 | GPIO4 | 예 |
| D5 | GPIO14 | 예(이 튜토리얼에서 사용) |
| D6 | GPIO12 | 예 |
| D7 | GPIO13 | 예 |
| D3 | GPIO0 | 아니요, 부팅 핀 |
| D4 | GPIO2 | 아니요, 부팅 핀 |
| D8 | GPIO15 | 아니요, 부팅 핀 |
| D0 | GPIO16 | 인터럽트 미지원이므로 RPM 코드에는 사용 불가 |
칩은 시작할 때 D3, D4, D8을 확인합니다. 센서는 OUT을 항상 구동합니다. 슬롯이 비어 있으면 OUT은 HIGH이고, D8에서는 이 HIGH 때문에 보드가 부팅하지 못할 수 있습니다. 디스크의 이빨이 우연히 슬롯 안에 있으면 OUT은 LOW이고, D3나 D4에서는 이 LOW 때문에도 정상 시작이 안 될 수 있습니다. 그러므로 센서를 이 세 핀에서 멀리 두세요.
IR 슬롯형 광학 속도 센서를 위한 프로그래밍 방법
설치할 라이브러리는 없습니다. 모든 것은 Arduino IDE에 추가한 ESP8266 코어에서 제공됩니다.
카운팅 코드의 단계
- 첫 단계는 OUT에 연결된 핀에 이름을 붙이는 것입니다. "D" 라벨에 주의하세요:
- 다음으로 setup()에서 핀을 입력으로 설정합니다. 센서가 선을 스스로 HIGH 또는 LOW로 만들므로 풀업은 필요하지 않습니다:
- 그런 다음 loop()를 한 번 돌 때마다 핀을 읽습니다. LOW는 ESP8266에게 빔이 끊겼다는 뜻입니다:
- 마지막으로 새 값을 바로 이전 값(lastState)과 비교합니다. 값이 LOW로 바뀐 경우에만 카운트가 올라갑니다. 그래서 카드가 슬롯에 5초 동안 꽂혀 있어도 한 번으로 셉니다.
RPM 코드의 단계
- 첫 단계는 펄스 카운터를 volatile로 만드는 것입니다. 인터럽트 함수가 백그라운드에서 값을 바꾸며, volatile 키워드는 컴파일러가 항상 실제 값을 읽도록 알려 줍니다:
- 다음으로 인터럽트 함수를 작성합니다. ESP8266에서는 이 함수 앞에 IRAM_ATTR이라는 단어가 반드시 있어야 합니다. 이것은 함수를 칩의 빠른 내부 RAM에 넣어 줍니다. 이것이 없으면 펄스가 들어올 때 ESP8266이 충돌하여 다시 시작할 수 있습니다:
- 그런 다음 setup()에서 함수를 D5에 연결합니다. FALLING은 OUT이 HIGH에서 LOW로 떨어질 때, 즉 이빨이 슬롯에 들어오는 순간에 함수가 실행된다는 뜻입니다:
- 그 후 1초에 한 번(millis()로 확인), 코드가 카운터를 복사하고 0으로 되돌립니다. ESP8266은 32비트 칩이므로 32비트 카운터를 한 번에 읽습니다. 그래서 이 버전에는 8비트 보드가 쓰는 noInterrupts()와 interrupts() 쌍이 필요하지 않습니다:
- 마지막으로 인코더 디스크 섹션의 공식으로 속도를 계산합니다:
슬롯 안의 물체를 세는 ESP8266 NodeMCU 코드
이 코드는 loop()에서 D5를 계속 읽습니다. 슬롯이 막힐 때마다 카운터에 1을 더하고, 상태가 바뀔 때만 한 줄을 출력합니다. 그래서 시리얼 모니터에 같은 메시지가 가득 차지 않습니다.
빠른 단계
- ESP8266을 처음 사용한다면 ESP8266 - 소프트웨어 설치을 참고하세요.
- 다이어그램과 같이 부품을 배선합니다.
- USB 케이블로 ESP8266 보드를 컴퓨터에 연결합니다.
- 컴퓨터에서 Arduino IDE를 엽니다.
- NodeMCU 1.0 (ESP-12E Module) 보드와 NodeMCU의 COM 포트를 선택합니다.
- 위 코드를 복사하여 Arduino IDE에 붙여넣습니다.
- Upload 버튼을 클릭하고 업로드가 끝날 때까지 기다립니다.
- 시리얼 모니터를 열고 9600 보레이트로 설정합니다.
- 카드 조각을 슬롯 안으로 밀어 넣었다가 뺍니다. 세 번 반복합니다.
- 시리얼 모니터에서 결과를 확인합니다.
슬롯에 아무것도 없는데 첫 줄이 "blocked"라고 나오나요? 그러면 모듈이 반대 로직입니다. if 문에서 LOW를 HIGH로 바꾸고 다시 업로드하세요.
모터 속도(RPM)를 측정하는 ESP8266 NodeMCU 코드
20슬롯 디스크가 돌면 초당 수백 개의 펄스가 생길 수 있습니다. loop()가 핀만 읽는 방식이라면, ESP8266이 예를 들어 텍스트를 출력하느라 바쁜 동안 일부 펄스를 놓치게 됩니다. 인터럽트가 이 문제를 해결합니다. 칩은 잠시 멈추고 countPulse()를 실행한 뒤 하던 일로 돌아가므로, 이빨이 하나도 빠짐없이 계산됩니다.
코드는 1초에 한 번 펄스 수와 속도를 출력합니다. SLOTS_PER_TURN 상수는 20입니다. 디스크의 구멍 수가 다르면 구멍을 세어서 이 숫자를 바꾸세요.
빠른 단계
- 배선은 그대로 둡니다. OUT은 D5에 그대로 있습니다. 옮기려면 D1, D2, D6 또는 D7을 고르고 코드의 SENSOR_PIN을 바꾸세요.
- 인코더 디스크를 모터 축이나 바퀴에 끼웁니다. 이빨이 슬롯 한가운데를 지나가고 플라스틱에 닿지 않도록 센서의 높이를 맞추세요.
- RPM 코드를 Arduino IDE에 붙여넣고 Upload를 클릭합니다.
- 시리얼 모니터를 9600 보레이트로 엽니다.
- 손가락으로 디스크를 돌리거나 모터를 작동시킵니다. NodeMCU로 모터를 구동하려면 ESP8266 - DC 모터 튜토리얼을 참고하세요.
- 시리얼 모니터에서 속도를 확인합니다.
이 테스트에서 모터는 300 RPM에 가깝게 돕니다. 펄스 101인 줄을 확인해 보세요: 101 x 60 / 20 = 303 RPM입니다. 첫 줄은 모터가 시작되기 전에 출력되었고, 마지막 줄은 모터가 멈춘 뒤에 출력되었습니다.
※ 주의:
디스크가 돌자마자 NodeMCU가 계속 다시 시작된다면 먼저 인터럽트 함수를 살펴보세요. ESP8266에서는 IRAM_ATTR이 붙어 있어야 합니다. 또한 매우 짧게 유지하세요: Serial.print()도, delay()도 쓰지 말고 카운터만 두세요.
추가 지식
자주 묻는 질문
센서를 더 강하게 하려고 VIN 핀에서 전원을 줘도 되나요?
아니요. VIN에는 USB 케이블의 5V가 흐르며, 그러면 OUT이 3.3V GPIO에 5V를 보내게 됩니다. 이 모듈은 3.3V에서도 잘 동작하므로 3V3 핀이 올바른 선택입니다.
RPM 값이 왜 3씩 단계적으로 움직이나요?
코드는 1초 동안 펄스를 온전한 개수로 셉니다. 슬롯이 20개일 때 펄스가 하나 더 늘어나면 60 / 20 = 3 RPM이 더해집니다. 슬롯이 더 많은 디스크는 더 작은 단계로 움직이고, 슬롯이 더 적은 디스크는 더 큰 단계로 움직입니다. 어떤 디스크를 쓰든 SLOTS_PER_TURN을 디스크에 맞추세요.
왜 CHANGE가 아니라 FALLING인가요?
FALLING은 이빨이 슬롯에 들어오는 순간에 이빨마다 한 번 함수를 실행합니다. CHANGE는 이빨이 나갈 때도 함수를 실행하므로, 이빨 하나당 두 번 세게 되어 실제 RPM의 두 배가 됩니다.
NodeMCU 하나로 속도 센서 두 개를 읽을 수 있나요?
네. 두 번째 센서를 D6 같은 다른 안전한 핀에 연결하고, 자체 volatile 카운터와 자체 IRAM_ATTR 함수를 만들어 주세요. 구동 바퀴가 두 개인 로봇 자동차에 유용합니다.
슬롯 센서, 장애물 센서, 로터리 엔코더?
슬롯 센서는 대상이 5.9 mm 틈을 항상 같은 위치로 통과해야 합니다. 통과할 때마다 깨끗한 펄스를 하나씩 주므로 RPM 측정과 카운팅에 가장 좋은 도구입니다.
ESP8266 - 장애물 센서는 열린 공간을 바라봅니다. 앞에 있는 벽, 손, 상자에서 반사되어 돌아오는 빛을 감지하므로, 대상이 슬롯에 들어갈 필요가 없습니다.
ESP8266 - 로터리 엔코더는 노브입니다. 두 개의 신호(CLK와 DT)와 푸시 버튼이 있어 회전 방향도 알 수 있습니다.
빔이 매 회전마다 같은 작은 위치에서 끊기기 때문에, 회전하는 부품의 시간을 재는 데는 슬롯형 광학 센서가 세 가지 중 가장 정밀함을 알 수 있습니다. 다만 방향은 알 수 없습니다. 방향이 필요하다면 로터리 엔코더를 선택하세요.
RPM에서 바퀴 속도로
디스크가 로봇 바퀴에 달려 있을 때는 한 단계를 더 거치면 RPM을 로봇이 움직이는 속도로 바꿀 수 있습니다:
- 바퀴 둘레 = π x 바퀴 지름
- 1초 동안 이동 거리 = (RPM / 60) x 바퀴 둘레
예: 지름 60 mm인 바퀴의 둘레는 약 188.5 mm입니다. 300 RPM에서는 초당 5바퀴를 돌므로, 로봇은 1초에 약 942 mm, 즉 0.94 미터를 굴러갑니다.
동영상
비디오 제작은 시간이 많이 걸리는 작업입니다. 비디오 튜토리얼이 학습에 도움이 되었다면, YouTube 채널 을 구독하여 알려 주시기 바랍니다. 비디오에 대한 높은 수요가 있다면, 비디오를 만들기 위해 노력하겠습니다.