ESP32 IR 슬롯형 광학 속도 센서

이 튜토리얼에서는 ESP32로 IR 슬롯형 광학 속도 센서의 상태를 읽고, 슬롯을 지나는 물체를 세고, 인코더 디스크에서 나오는 펄스를 모터 속도(RPM)로 바꾸어 시리얼 모니터에 출력하는 방법을 알려 드립니다.

ESP32와 ir 슬롯형 광학 속도 센서

준비물

1×38-pin ESP32 ESP-WROOM-32 Dev Module - Narrow 쿠팡 | 아마존
1×(또는) 38-pin ESP32 ESP-WROOM-32 Dev Module - Wide 쿠팡 | 아마존
1×(또는) 30-pin ESP32 ESP-WROOM-32 Dev Module - Wide 아마존
1×(또는) ESP32 Uno-form board 아마존
1×(또는) ESP32 S3 Uno-form board 아마존
1×USB 케이블 타입-A to 타입-C (USB-A PC용) 쿠팡 | 아마존
1×USB 케이블 타입-C to 타입-C (USB-C PC용) 아마존
1×(옵션) DC 커넥터 전원 연결 잭 플러그 소켓 쿠팡 | 아마존
1×IR Slotted Optical Speed Sensor 아마존
1×점퍼케이블 쿠팡 | 아마존
1×(옵션) Breadboard 쿠팡 | 아마존
1×(추천) ESP32용 스크루 터미널 확장 보드 쿠팡 | 아마존
1×(추천) Breakout Expansion Board for ESP32 쿠팡 | 아마존
1×(추천) ESP32용 전원 분배기 쿠팡 | 아마존
공개: 이 포스팅 에 제공된 일부 링크는 아마존 제휴 링크입니다. 이 포스팅은 쿠팡 파트너스 활동의 일환으로, 이에 따른 일정액의 수수료를 제공받습니다.

IR 슬롯형 광학 속도 센서에 대하여

이 작은 모듈은 가운데에 좁은 틈이 있는 U자 모양입니다. 포토 인터럽터, 옵토 인터럽터, U자형 IR 센서, 또는 간단히 슬롯 센서 등 여러 이름으로 불립니다. 하는 일은 하나입니다. 틈 안에 무언가 있는지 없는지를 ESP32에 알려 줍니다. 아주 빠르게 전환할 수 있어서 바퀴나 모터가 얼마나 빨리 도는지 측정하는 데 좋은 선택입니다.

IR 슬롯형 광학 속도 센서
센서 종류 슬롯형 광전 센서(IR LED + NPN 포토트랜지스터)
슬롯 폭 5.9 mm
출력 디지털(TTL), 막히면 LOW, 비어 있으면 HIGH
신호 처리 내장 슈미트 트리거
장착 방식 양쪽 끝에 M3 나사 구멍
핀 수 3개 (VCC, GND, OUT)
동작 전압 3.3V ~ 5V DC

대표적인 용도는 인코더 디스크를 이용한 모터 속도(RPM) 측정, 간단한 회전계, 물체나 펄스 세기, 바퀴 회전 수를 세어 거리 측정하기, 로봇 자동차의 바퀴 속도 피드백, 한계 위치나 위치 감지입니다.

IR 슬롯형 광학 속도 센서 핀 배치

ir 슬롯형 광학 속도 센서 핀 배치
  • VCC 핀: 이 핀을 ESP32의 3.3V 핀에 연결합니다
  • GND 핀: 이 핀을 GND(0V)에 연결합니다
  • OUT 핀: 이 핀을 ESP32의 입력 핀에 연결합니다(이 튜토리얼에서는 GPIO18). 슬롯이 막히면 LOW, 비어 있으면 HIGH를 출력합니다

핀 순서는 제조 시기에 따라 항상 같지는 않습니다. 선을 연결하기 전에 가지고 있는 모듈에 인쇄된 표시를 확인하세요.

OUT 핀은 VCC에 준 전압만큼 높게 올라갑니다. ESP32는 3.3V 보드이므로 센서를 5V가 아니라 3.3V 핀에서 전원을 공급하세요. 이렇게 하면 OUT 핀이 GPIO 핀에 3.3V보다 높은 전압을 보내는 일이 없습니다.

IR 슬롯형 광학 속도 센서 작동 원리

ir 슬롯형 광학 속도 센서 작동 원리

U자의 한쪽 팔에는 적외선 LED가 있습니다. 다른 쪽 팔에는 NPN 포토트랜지스터가 있습니다. 둘은 5.9 mm 틈을 사이에 두고 서로 마주 보고 있습니다.

  • 틈에 아무것도 없을 때: IR 빛이 포토트랜지스터에 닿고, OUT 핀은 HIGH입니다.
  • 틈에 불투명한 물체가 있을 때(예: 종이 카드 조각이나 인코더 디스크의 이빨 하나): 빛이 차단되고, OUT 핀은 LOW입니다.

보드의 슈미트 트리거가 거친 빛의 세기를 둘 사이에서 흔들림 없는 깨끗한 0 또는 1로 바꾸어 줍니다. 덕분에 ESP32 코드에는 디바운스가 필요하지 않습니다.

투명한 플라스틱은 IR 빛을 통과시킬 수 있어서 항상 막힌 것으로 감지되지는 않습니다. 속이 비치지 않는 물체를 사용하세요.

다른 제조사의 일부 모듈은 반대로 동작합니다. 틈이 비어 있는데 센서가 "막힘"이라고 한다면, 첫 번째 코드에서 LOW와 HIGH만 바꾸면 됩니다. RPM 코드는 디스크의 슬롯마다 에지를 하나씩 세기 때문에 두 종류 모두에서 동작합니다.

선연결

ESP32와 IR 슬롯형 광학 속도 센서를 연결하는 방법

선은 세 개만 필요합니다. VCC는 3.3V에, GND는 GND에, OUT은 GPIO18에 연결합니다. 선을 핀에 바로 꽂아도 되고, 원하면 브레드보드를 사용해도 됩니다.

ESP32 ir 슬롯형 광학 속도 센서 배선도

이 이미지는 Fritzing을 사용하여 만들어졌습니다. 이미지를 확대하려면 클릭하세요.

ESP32 및 다른 구성 요소에 전원을 공급하는 방법에 대해 잘 알지 못하는 경우, 다음 튜토리얼에서 안내를 찾을 수 있습니다: ESP32 전원 공급 방법.

IR 슬롯형 광학 속도 센서 ESP32
VCC 3.3V
GND GND
OUT GPIO18

속도 측정을 위해 인코더 디스크를 설치하는 방법

속도를 측정하려면 센서가 돌아가는 동안 빛을 계속 반복해서 끊어 주는 무언가가 필요합니다. 그것이 인코더 디스크의 역할입니다. 디스크를 모터 축이나 바퀴에 고정한 다음, 디스크의 이빨이 틈을 지나가도록 M3 구멍으로 센서를 고정하세요. 디스크는 회전하는 어느 지점에서도 센서에 닿으면 안 됩니다.

처음 테스트할 때는 디스크를 손으로 돌려 볼 수 있습니다. 모터로 돌리려면 모터에 별도의 배선이 필요하므로 ESP32 - DC 모터을 참고하세요.

IR 슬롯형 광학 속도 센서를 위한 프로그래밍 방법

라이브러리는 필요하지 않습니다. 아래 두 예제는 ESP32 코어에 포함된 함수만 사용합니다.

  • 핀을 입력으로 설정합니다: pinMode(SENSOR_PIN, INPUT);
  • 슬롯의 상태를 읽습니다(LOW는 막힘): int state = digitalRead(SENSOR_PIN);
  • 상태가 바뀔 때만 무언가를 합니다: if (state != lastState) { ... }
  • 이빨이 슬롯을 막을 때마다 짧은 함수를 호출합니다: attachInterrupt(digitalPinToInterrupt(SENSOR_PIN), countPulse, FALLING);
  • ESP32가 빠르게 실행할 수 있도록 그 함수에 IRAM_ATTR을 붙입니다: void IRAM_ATTR countPulse() { pulseCount++; }
  • 1초 동안의 펄스를 분당 회전수로 바꿉니다: float rpm = pulses * 60.0 / SLOTS_PER_TURN;

속도에 왜 인터럽트를 쓸까요? 모터가 빠르게 돌면 펄스가 서로 아주 가까이 오기 때문에 loop() 안의 단순한 확인으로는 일부를 놓칠 수 있습니다. 인터럽트는 하나도 빠짐없이 잡아냅니다. 이빨마다 한 번만 세어지도록 FALLING 에지를 선택했습니다. 더 알고 싶다면 ESP32 - GPIO 인터럽트을 읽어 보세요.

ESP32 코드 - 슬롯 안의 물체 감지 및 개수 세기

이 코드는 OUT 핀을 계속 반복해서 확인합니다. 상태가 바뀔 때만 메시지를 출력합니다. 슬롯이 막힐 때마다 카운터가 하나씩 올라갑니다.

/* * 이 ESP32 코드는 newbiely.kr 에서 개발되었습니다 * 이 ESP32 코드는 어떠한 제한 없이 공개 사용을 위해 제공됩니다. * 상세한 지침 및 연결도에 대해서는 다음을 방문하세요: * https://newbiely.kr/tutorials/esp32/esp32-ir-slotted-optical-speed-sensor */ const int SENSOR_PIN = 18; // ESP32 GPIO18 connected to the OUT pin of the speed sensor int lastState; // the previous state of the sensor int objectCount = 0; // how many times the slot was blocked void setup() { Serial.begin(9600); pinMode(SENSOR_PIN, INPUT); lastState = digitalRead(SENSOR_PIN); } void loop() { int state = digitalRead(SENSOR_PIN); if (state != lastState) { // the state has changed if (state == LOW) { // LOW = something is in the slot objectCount++; Serial.print("The slot is blocked - count: "); Serial.println(objectCount); } else { // HIGH = the slot is clear Serial.println("The slot is clear"); } lastState = state; } }

빠른 단계

ESP32를 처음 사용한다면 ESP32 - 소프트웨어 설치을 참고하세요.

  • 배선도와 같이 센서를 ESP32에 연결합니다.
  • USB 케이블을 ESP32와 PC에 연결합니다.
  • Arduino IDE를 열고 ESP32 Dev Module 보드와 올바른 COM 포트를 선택합니다.
  • 위 코드를 복사하여 Arduino IDE에 붙여넣습니다.
  • Arduino IDE에서 Upload 버튼을 클릭하여 코드를 컴파일하고 ESP32에 업로드합니다.
  • Serial Monitor 아이콘을 클릭한 다음 baud rate를 9600으로 입력하거나 선택합니다.
  • 종이 카드 조각이나 손가락을 슬롯에 넣었다가 빼 보세요. 몇 번 반복합니다.
  • 시리얼 모니터의 메시지를 확인합니다.
∞
Newbiely | Arduino IDE 2.3.8
──
☐
✕
File
Edit
Sketch
Tools
Help
ESP32 Dev Module
Newbiely.ino
···
8 Serial.println("Hello World!");
Output
Serial Monitor
Message (Enter to send message to 'ESP32 Dev Module' on 'COM15')
New Line
9600 baud
The slot is blocked - count: 1 The slot is clear The slot is blocked - count: 2 The slot is clear The slot is blocked - count: 3 The slot is clear
Ln 11, Col 1
ESP32 Dev Module on COM15
2

ESP32 코드 - 모터 속도(RPM) 측정

이제 센서가 회전계로 동작합니다. 슬롯을 막는 디스크의 이빨마다 인터럽트가 실행되어 카운터에 1을 더합니다. 1초에 한 번 코드가 카운터를 읽고, 0으로 되돌리고, 속도를 계산합니다.

계산은 간단합니다. TT 기어 모터와 함께 파는 것과 같은 일반적인 인코더 디스크는 슬롯이 20개라서 한 바퀴에 펄스가 20개 나옵니다. 1초 동안의 펄스에 60을 곱하면 1분 동안의 펄스가 됩니다. 이를 20으로 나누면 분당 회전수(RPM)를 얻습니다. 디스크의 슬롯 수가 다르다면 코드에서 SLOTS_PER_TURN의 값을 바꾸세요.

/* * 이 ESP32 코드는 newbiely.kr 에서 개발되었습니다 * 이 ESP32 코드는 어떠한 제한 없이 공개 사용을 위해 제공됩니다. * 상세한 지침 및 연결도에 대해서는 다음을 방문하세요: * https://newbiely.kr/tutorials/esp32/esp32-ir-slotted-optical-speed-sensor */ const int SENSOR_PIN = 18; // ESP32 GPIO18 connected to the OUT pin of the speed sensor const int SLOTS_PER_TURN = 20; // number of slots (holes) in the encoder disc volatile unsigned long pulseCount = 0; // changed inside the interrupt unsigned long lastTime = 0; // runs every time a tooth of the disc blocks the slot void IRAM_ATTR countPulse() { pulseCount++; } void setup() { Serial.begin(9600); pinMode(SENSOR_PIN, INPUT); attachInterrupt(digitalPinToInterrupt(SENSOR_PIN), countPulse, FALLING); } void loop() { if (millis() - lastTime >= 1000) { // every 1 second lastTime = millis(); unsigned long pulses = pulseCount; // read and reset the counter pulseCount = 0; float rpm = pulses * 60.0 / SLOTS_PER_TURN; // pulses per second -> turns per minute Serial.print("Pulses: "); Serial.print(pulses); Serial.print(" | Speed: "); Serial.print(rpm); Serial.println(" RPM"); } }

빠른 단계

  • 위의 인코더 디스크 그림처럼 인코더 디스크와 센서를 고정합니다. ESP32와의 배선은 그대로입니다.
  • 위 코드를 복사하여 Arduino IDE에 붙여넣고 Upload 버튼을 클릭합니다.
  • 시리얼 모니터를 9600 baud로 엽니다.
  • 디스크를 손으로 돌리거나 모터를 켭니다.
  • 시리얼 모니터에서 속도를 확인합니다. 아래 예는 약 300 RPM으로 도는 모터이며, 처음과 끝에서는 모터가 멈춰 있습니다.
∞
Newbiely | Arduino IDE 2.3.8
──
☐
✕
File
Edit
Sketch
Tools
Help
ESP32 Dev Module
Newbiely.ino
···
8 Serial.println("Hello World!");
Output
Serial Monitor
Message (Enter to send message to 'ESP32 Dev Module' on 'COM15')
New Line
9600 baud
Pulses: 0 | Speed: 0.00 RPM Pulses: 98 | Speed: 294.00 RPM Pulses: 101 | Speed: 303.00 RPM Pulses: 100 | Speed: 300.00 RPM Pulses: 99 | Speed: 297.00 RPM Pulses: 0 | Speed: 0.00 RPM
Ln 11, Col 1
ESP32 Dev Module on COM15
2

바퀴가 얼마나 멀리 갔는지도 알고 싶나요? 회전수에 바퀴 둘레(π × 바퀴 지름)를 곱하세요.

슬롯 안이 아니라 몇 센티미터 떨어진 물체를 감지하고 싶다면 ESP32 - 적외선 장애물 회피 센서을 참고하세요. 회전 방향도 알려 주는 노브가 필요하다면 ESP32 - 로터리 엔코더을 참고하세요.

동영상

비디오 제작은 시간이 많이 걸리는 작업입니다. 비디오 튜토리얼이 학습에 도움이 되었다면, YouTube 채널 을 구독하여 알려 주시기 바랍니다. 비디오에 대한 높은 수요가 있다면, 비디오를 만들기 위해 노력하겠습니다.

댓글