Based on contributions by ThomasVrakking.
Use this guide when you need to count discrete objects (parts, products) moving past a fixed point — for example, metal objects falling through a chute, or items passing on a conveyor. It compares the common sensor options and gives a working Arduino counter for the option that usually wins: a photoelectric sensor.
What you need
- An Arduino (or similar microcontroller) if you use the counting code below.
- A sensor matching your chosen technology (see comparison below).
- Basic wiring: a digital input pin and, for most sensor types, a separate power supply for the sensor.
Comparing sensor options
The right sensor depends on your object material, speed, and environment. This comparison is based on counting metal objects falling through a chute, but the trade-offs generalize to most conveyor/chute counting tasks.
| Sensor type | Works well when | Watch out for |
|---|---|---|
| Vision (camera) | You also need to identify/classify objects, not just count them | Most flexible option but also the most difficult and time-consuming to set up; likely overkill for simple counting |
| Inductive | Detecting metal objects at very short range | Limited range: up to ~15 mm standard, ~40 mm for long-range types — often too short for a chute |
| Capacitive | Detecting metallic or non-metallic objects (plastic, liquid, powder, wood) | Larger range (~60 mm) but sensitive to dust, humidity, and temperature — can cause false positives in a factory environment |
| Hall-effect | Detecting magnetized objects specifically | Poor fit for ordinary (non-magnetized) metal parts |
| Load cell | Weighing objects as they land | Vibration and mechanical noise in a factory setting cause false positives; generally unreliable for counting |
| Mechanical button/limit switch | A simple, low-cost mechanical setup | Needs a precisely tuned spring force so it triggers reliably per object but not from vibration |
| LDR (light-dependent resistor) | Detecting large changes in light intensity | On a metal-on-metal chute, reflections are too similar in intensity to reliably distinguish objects |
| Break-beam – ultrasonic | Slower-moving objects | Detection time may be too slow for fast-falling objects |
| Break-beam – infrared | Simple presence detection | Needs precise emitter/receiver alignment, which is hard to maintain in an industrial setting |
| Break-beam – photoelectric | Most counting applications | Recommended default — see below |
Recommended: photoelectric sensor
A photoelectric (break-beam) sensor was the best fit for counting metal objects falling through a chute, for several reasons:
- Fast response time, suitable for fast-moving, falling objects.
- Easy to install and align, especially combined with a reflector to enlarge the detection area.
- Not very sensitive to vibration, dust, or lighting changes — unlike capacitive or load-cell sensors.
- Simple digital output (PNP/NPN) that’s easy to read with a microcontroller or PLC.
- Cost-effective and available in many detection ranges to match your chute or conveyor width.
- Easy to retrofit into an existing setup with minimal changes.
Steps: counting with a photoelectric sensor and Arduino
1. Wire the sensor
Connect the sensor’s digital output to a digital input pin on the Arduino (pin 3 in the example below), and power the sensor according to its datasheet (most photoelectric sensors need their own supply voltage, separate from the Arduino’s 5V logic).
2. Upload the counting sketch
This sketch debounces the sensor reading (checks it multiple times before accepting a detection) and enforces a minimum time between counted objects, to avoid counting one object twice.
#define SENSOR_PIN 3 // sensor output connected to digital pin 3
int count = 0;
void setup() {
Serial.begin(115200);
pinMode(SENSOR_PIN, INPUT);
}
void loop() {
static unsigned long lastDetectionTime = 0;
static bool wasDetected = false;
// Read the sensor multiple times for stability
bool stableLow = true;
for (int i = 0; i < 5; i++) {
if (digitalRead(SENSOR_PIN) != LOW) {
stableLow = false;
break;
}
delay(2); // 5 reads x 2 ms = 10 ms check window
}
if (stableLow && !wasDetected) {
if (millis() - lastDetectionTime > 75) { // debounce window
count++;
Serial.print("Count: ");
Serial.println(count);
if (count == 300) count = 0; // reset after 300 objects
lastDetectionTime = millis();
wasDetected = true;
}
} else if (digitalRead(SENSOR_PIN) == HIGH) {
wasDetected = false;
}
}
This example resets the count after 300 objects and assumes the sensor output goes LOW when the beam is broken (object present) — check your sensor’s datasheet, since some photoelectric sensors are wired the other way around (output HIGH when triggered). If your counts don’t move when objects pass, this is the first thing to check.
Check: the source code included a
delay(1000)immediately after incrementing the count, which pauses the whole loop (including sensor reads) for a full second after every detection. This has been removed here since it would cause objects passing faster than roughly 1 per second to be missed; the 75 ms debounce window already prevents double-counting a single object. If you need a cooldown between objects, tune the debounce window instead.
3. Test at your actual object speed
The debounce window (75 ms) and read window (10 ms) were tuned for the original chute setup. If your objects fall or move faster or slower, adjust these values: too short a debounce window risks double-counting a single object; too long a window risks missing two objects that pass close together.
Related
Rewritten and consolidated (Sept 2026) from the original student how-to’s: How to count.