Aliases: photo interrupter, optical endstop, speed sensor, slot sensor.
An infrared LED in one arm of a U, a phototransistor in the other, and a gap between them. Anything opaque in the gap cuts the beam. It is how a printer finds home, how a robot car counts wheel turns, and how a class measures the speed of a fan.
Pins
| Pin | What it does |
|---|---|
SIG |
Printed S. LOW while the beam gets through, HIGH while something is in the slot. |
VCC |
Printed +. Supply, 3.3 V or 5 V. |
GND |
Printed -. Ground. |
Properties
slots is how many slots the encoder disc has, 20 by default: the black disc that
comes with two-wheel robot chassis.
wheel (Wheel on in the properties) is what turns the disc: the slider on the part (the default), or any DC
motor or encoder gear motor in the circuit. It is saved with the project as the
motor's id.
While it runs
The slider spins the wheel through the slot, 0 to 600 RPM. The card beside it is a piece of cardboard: click it to push it into the slot, and again to pull it out. The beam drawn across the gap is lit while light gets through.
On a motor
Pick a motor under Wheel on and the disc turns with that motor's output shaft, after its gearbox: the speed the motor itself shows. It follows the motor model from moment to moment, so it spins up and coasts down with the motor, and turns either way round (one beam cannot tell which). The slider gives way to the motor's name and the wheel's speed, and does nothing; the card still works. Delete the motor and the wheel goes back to the slider.
The pulses come exactly when the shaft brings each slot round, so a sketch that counts them measures the motor's real speed, including the dead band and the lag of a geared motor on PWM. A wheel that stops rests wherever it stopped, slot or spoke.
Counting the wheel
Every slot is one pulse on SIG, so
RPM = pulses a second x 60 / slots
Count rising edges with an interrupt and work out the RPM once a second:
const byte SLOTS = 20;
volatile unsigned int pulses = 0;
void countSlot() { pulses++; }
void setup() {
Serial.begin(9600);
pinMode(3, INPUT);
attachInterrupt(digitalPinToInterrupt(3), countSlot, RISING);
}
void loop() {
delay(1000);
noInterrupts();
unsigned int n = pulses;
pulses = 0;
interrupts();
Serial.print(n * 60UL / SLOTS);
Serial.println(" RPM");
}
What the model gets right
Blocked is high. The board puts a 10 k pull-up on the phototransistor's
collector. Light turns the transistor on and pulls SIG low; blocking the beam lets
the pull-up take it high.
The saturation voltage. From the Everlight ITR9608 datasheet, the class of part
on these boards: at least 0.5 mA of collector current with the LED on, and 0.4 V at
most across the transistor at that current. Beam through, SIG sits at 0.4 V.
The edge time. The sheet's rise and fall time is 15 µs, and SIG follows the
beam 15 µs late. A slot that passes faster than that is not seen cleanly on the real
part either.
The wheel. Slots and spokes are the same width, so the beam is open half of each slot period. A stopped wheel on the slider rests on a slot, with the beam through.
What it does not model
Ambient light, partial blocking, and the LED current.
Common mistakes
Reading it the wrong way around: HIGH means blocked.
Counting in loop() with digitalRead. At a few hundred RPM a 20-slot wheel makes
pulses a few milliseconds long, and a loop that also prints misses them; use an
interrupt.
See it in action
Heat, magnet and wheel counts a 20-slot wheel on pin 3 and prints the RPM. Open it at /templates.