DIY Bidirectional Visitor Counter Circuit Schematic and Step-by-Step Guide

Implement an infrared proximity pair arrangement staggered at 10 cm vertical offset to prevent ambient light interference–critical for accurate entry/exit detection in high-traffic zones. Use an Atmega328P microcontroller configured with Timer2 in CTC mode at 8 MHz for precise pulse-width modulation of the IR emitters. This setup achieves sub-50 millisecond response times, essential for distinguishing simultaneous crossings.
Power regulation demands a 7805 voltage regulator with heatsink, as continuous operation at 500 mA load generates 2.5W thermal dissipation. Bypass capacitors (0.1 µF ceramic) must be placed within 3 mm of the microcontroller VCC/GND pins to suppress transient spikes that skew sensor readings. For environments with fluorescent lighting, add a 330 Ω resistor in series with each IR LED to mitigate 50/60 Hz flicker coupling into the receiver path.
Signal conditioning requires a two-stage amplification: an initial 10 kΩ transimpedance amplifier followed by an active bandpass filter centered at 38 kHz with 1.5 kHz bandwidth. This rejects noise while preserving the coded pulse train used for direction determination. Store counts in separate registers for ingress/egress, updating only after both sensors confirm a complete crossing sequence–otherwise, reset the pending state machine.
Testing reveals optimal sensor spacing of 1.2 meters for 95% accuracy with typical adult gait patterns. Narrower spacing (1.5 m) fails to capture rapid sequential movements. Calibrate receiver sensitivity thresholds using a 1 kΩ potentiometer to achieve a 3V swing at the ADC input for unobstructed beam detection.
Designing a Two-Way People Tracking System
Start with a pair of infrared transmitters and receivers positioned across the entrance at heights of 80 cm and 120 cm. Space the lower beam 30 cm from the floor and the upper beam 50 cm above it. Use the HC-SR04 sensors for basic setups, but switch to TCRT5000 modules if ambient light exceeds 500 lux. Connect both sensors to a dual-channel comparator like the LM393 to filter noise before feeding signals into an ATmega328P microcontroller.
Program the controller to recognize entry sequences: a low-to-high transition on the lower beam followed by the upper beam within 200 ms signals movement inward. Reverse the order for exits. Implement a 10-second debounce buffer to ignore double-counts from wheelchairs or carts. Store counts in non-volatile memory using the microcontroller’s EEPROM–allocate 4 bytes per hour to track peak periods. For accuracy, cross-validate sensor data with a PIR module (HC-SR501) in parallel when foot traffic exceeds 200 people per hour.
Display real-time data using a 4-digit 7-segment LED driven by a MAX7219 chip, consuming 3.3V and simplifying wiring. Alternatively, connect to an ESP8266 via UART for cloud logging. Use MQTT protocol with a QoS=1 level to ensure packet delivery over unstable Wi-Fi–buffer unsent data in flash memory for up to 24 hours if connectivity drops. Power the system with a 9V 1A adapter and regulate down to 5V using an AMS1117; add a 4700µF capacitor near the microcontroller to eliminate voltage spikes from sensor activation.
Calibrate the system monthly: walk through the doorway at speeds of 0.5 m/s to 2 m/s while monitoring latencies. Adjust the comparator’s threshold between 1.5V and 2.2V based on local dust levels–higher voltages reduce false triggers from airborne particles. For outdoor deployments, replace the TCRT5000 with VL53L0X ToF sensors, extending range to 1.5 meters while ignoring reflective surfaces like metal doors. Isolate analog and digital grounds using a ferrite bead to prevent crosstalk between the comparator and microcontroller.
Expand functionality by adding a DS3231 real-time clock to timestamp entries. Log hourly summaries to an SD card in CSV format, including temperature data from a DHT22 sensor to correlate traffic with environmental conditions. For adhesive mounting, use industrial Velcro rated to 5 kg shear force–position sensors behind perforated plastic enclosures (IP54) to prevent dust ingress without blocking IR beams.
Key Components Selection for IR Sensor-Based People Tracking
Opt for the TCRT5000 reflective IR module for proximity detection, prioritizing its 5mm sensing distance and integrated comparator output to eliminate external amplification needs. Pair it with an LM393 differential comparator if signal conditioning is required, ensuring a 10kΩ pull-up resistor on the output for stable logic-level transitions. For mobile deployments, the GP2Y0A21YK0F Sharp sensor provides a 10–80cm range with analog output, demanding an ADC input on the microcontroller–allocate at least 10-bit resolution for reliable differentiation between objects.
Select microcontrollers with the lowest quiescent current to maximize battery life in edge installations. The ATmega328P consumes 0.2µA in power-down mode, making it ideal for solar-powered units, while the ESP8266 requires 20µA but offers Wi-Fi telemetry for real-time data. For wired systems, the STM32L0 series balances 8µA standby current with 32-bit processing, sufficient for dual-sensor interrupts without latency. Always match GPIO voltage levels–TCRT5000 operates at 5V, while ESP variants need level shifters if interfacing with 3.3V logic.
Power Supply Considerations

| Component | Voltage Range (V) | Typical Current (mA) | Recommended Regulator |
|---|---|---|---|
| TCRT5000 | 3.3–5.5 | 10–20 | AP2112K (LDO, 600mA) |
| Sharp GP2Y0A21YK0F | 4.5–5.5 | 20–30 | AMS1117 (1A, 1% tolerance) |
| ATmega328P | 1.8–5.5 | 5–15 | None (direct LiPo connection) |
| ESP8266 | 3.0–3.6 | 70–80 (active) | MIC5205 (500mA, low dropout) |
Use aluminum electrolytic capacitors rated at 105°C for input filtering on regulators–100µF on the input and 10µF on the output prevent voltage spikes during sensor activation. For low-power designs, add a 0.1µF ceramic capacitor in parallel to bypass high-frequency noise. Avoid linear regulators for currents above 200mA; switch to MP2307 buck converters (95% efficiency) if multiple sensors run simultaneously, reducing thermal dissipation in enclosed housing.
Implement hysteresis in the detection logic to prevent oscillations near the threshold. A 47kΩ feedback resistor on the LM393 comparator creates a 5% hysteresis band, filtering false triggers from ambient light changes. For dual-direction logic, assign dedicated interrupt pins–Arduino’s INT0/INT1 or STM32’s EXTI–with pull-down resistors to ensure clean transitions. Test sensor alignment under worst-case conditions: TCRT5000 misalignment beyond ±15° degrades accuracy by 30%, while Sharp sensors tolerate ±20° before signal attenuation occurs.
Environmental and Mechanical Constraints
Encase sensors in matte-black ABS plastic to block stray infrared interference; a 0.5mm wall thickness minimizes signal attenuation while allowing 85% transmission. Mount Sharp sensors at 45° for ceiling deployments to optimize ground coverage–vertical alignment reduces range by 40%. For outdoor use, select TCRT5000 variants with daylight filters (e.g., Vishay’s TSSP4038) to suppress 50/60Hz noise from fluorescent lighting; these require an additional 5kΩ series resistor to limit current surges. Calibrate detection thresholds empirically–standard white surfaces reflect 90% of IR, while black surfaces absorb 70%, necessitating a 20% adjustment in comparator reference voltage.
Step-by-Step Assembly of Dual Seven-Segment Display Output
Begin by positioning two common-cathode seven-segment modules side-by-side on a breadboard, aligning their pin rows to avoid overlaps. Use 220-ohm resistors for each segment (pins a–g) to limit current–connect them directly to the microcontroller’s output pins without intermediaries. For the decimal point (pin dp), either omit it or ground it through a resistor if unused. Verify the pinout of your specific display model (e.g., Kingbright SA52-11 or Lite-On LTS-546); common-cathode units require a shared ground, while common-anode variants need a +5V pull-up.
- Wire the left digit’s cathode to a transistor (e.g., 2N2222) to handle multiplexing; connect the base to a microcontroller pin via a 1k resistor. Repeat for the right digit.
- Assign eight microcontroller pins (e.g., Arduino Uno’s D2–D9) to control segments a–g and dp. Use direct port manipulation for faster updates if timing is critical–e.g.,
PORTD = segment_pattern;. - Implement multiplexing with a 5–10ms refresh rate per digit. Enable one transistor at a time while sending the corresponding segment data to the shared bus. Overlap transistor switching by 1µs to prevent ghosting.
- Test each segment individually by toggling pins in sequence before integrating them into the full count logic. Use an oscilloscope to confirm clean transitions and no voltage sag on shared lines.
For stability, add 0.1µF decoupling capacitors across each display’s power pins. If flicker persists, reduce multiplexing intervals or use a dedicated driver IC like the MAX7219–though it requires SPI initialization. When soldering, bundle wires by function (e.g., segment lines, cathodes) and use 26–28 AWG wire for minimal resistance drop over long runs. Avoid exceeding 20mA per segment; consult the datasheet for absolute maximum ratings and derate by 20% for longevity.
Programming Logic for Dynamic Entry Tracking in Embedded Systems

Assign interrupt service routines (ISRs) to external triggers like infrared beams to ensure immediate response without polling delays. Use rising or falling edge detection based on sensor polarity–opt for rising edges with active-high signals to avoid false triggers from noise. For AVR microcontrollers, configure pins as INPUT_PULLUP to stabilize readings; for STM32, enable pull-down resistors via GPIO settings when default states are critical.
Implement hysteresis in the counting logic by requiring two consecutive valid readings before updating internal registers. This prevents spurious counts from single-point failures–store the raw sensor state in a volatile uint8_t variable and compare it against a non-volatile variable updated only after confirmation. For example, in Arduino-like environments, use a sequence like:
if ((current_state == HIGH) && (last_confirmed_state == LOW)) {
if (debounce_buffer++ > DEBOUNCE_THRESHOLD) {
count++;
last_confirmed_state = HIGH;
}
}
Adjust DEBOUNCE_THRESHOLD (typically 2-5 cycles) to match environmental conditions.
State Machine Integrity

Structure the core logic as a finite state machine (FSM) with states for IDLE, INCREMENT_PENDING, DECREMENT_PENDING, and LOCK. Transitions occur only after hysteresis validation–never update the master count directly from ISRs to prevent race conditions. For ARM Cortex-M devices, leverage hardware features like the SysTick timer to force FSM evaluation at fixed intervals (e.g., 10ms), reducing CPU load while maintaining real-time responsiveness.
Segment count handling into directional buffers (entry/exit) to monitor flow independently. Use separate uint16_t variables for each direction, incrementing one while decrementing the other only if net values remain within predefined bounds (e.g., max_occupancy). Apply saturation arithmetic to prevent overflow:
if ((direction == ENTRY) && (entry_countThis ensures data integrity even during rapid transitions.
Persistent Storage and Recovery
Sync the RAM-based count with non-volatile storage (EEPROM/flash) at fixed intervals or during low-power states to preserve data across resets. For PIC microcontrollers, use the DATA EE module; for ESP32, leverage Preferences library. Implement a checksum (XOR-sum of count bytes) to detect corruption–only commit changes if the checksum validates. Example recovery logic:
if (eeprom_checksum == calculate_checksum(count_value)) { current_count = eeprom_read(COUNT_ADDRESS); } else { current_count = DEFAULT_VALUE; eeprom_write(COUNT_ADDRESS, current_count); eeprom_write(CHECKSUM_ADDRESS, calculate_checksum(current_count)); }Add a 50ms delay after writes to ensure flash stability.
Avoid floating-point operations–use fixed-point arithmetic for calculations involving net values. For example, if calibrating sensor offsets, scale readings by 1000 and store as int32_t to retain precision without performance penalties. During UART/serial output, format values as ASCII strings directly from the fixed-point variables to prevent runtime conversion errors. Test edge cases (e.g., MAX_VALUE - 1 to MAX_VALUE transitions) with automated scripts simulating 10k+ events to verify robustness.