Smart Classroom
Occupancy Counter
Build a smart sensor that counts every student walking in or out of the classroom door — and shows the live headcount instantly! 🚪➕➖
How Does an Occupancy Counter Work? 🤔
Two Sensors Guard the Doorway!
Imagine two invisible laser trip-wires placed one behind the other at the classroom door. When a student walks IN, they break the outer beam first, then the inner beam. When someone walks OUT, it happens in reverse order! The sequence tells the Arduino which direction they went.
Counting Up and Down Like a Scoreboard
Every time someone enters, the Arduino adds 1 to the count. Every time someone exits, it subtracts 1. Just like a basketball scoreboard that goes up when your team scores! The current total is always the number of people inside right now.
The LCD Screen is the Announcer
An LCD display mounted near the door shows the live headcount, just like a digital scoreboard at a stadium. Teachers can glance at it to instantly know how many students are present — no manual roll call needed!
The Full Detection Journey 🔄
Reading the Direction 🧭
🟢 ENTERING (Count +1)
Outer sensor (S1) triggers first, then inner sensor (S2). Student is walking INTO the room.
🔴 EXITING (Count −1)
Inner sensor (S2) triggers first, then outer sensor (S1). Student is walking OUT of the room.
Parts You'll Need 🛒
All available at electronics shops or online stores like Robu.in, Robocraze, or Amazon. Ask a parent or teacher to help you buy them!
What is a Beam-Break Sensor? Our IR sensors shoot invisible infrared light across the doorway. When nothing blocks it, the receiver "sees" the light — beam is clear. When someone walks through, their body blocks the beam for a split second — that's our trigger signal!
Circuit Diagram & Wiring 🔌
Safety first! Always unplug Arduino from USB before changing any wires. Double-check the LCD pin order before connecting — wrong wiring can damage the display!
Complete Wiring Table
| # | From | To | Wire | Purpose |
|---|---|---|---|---|
| 1 | Arduino 5V | Sensor 1 & 2 VCC | YELLOW | Power both IR sensors |
| 2 | Arduino GND | Sensor 1 & 2 GND | BLACK | Ground for sensors |
| 3 | IR Sensor 1 OUT (Outer) | Arduino Pin D2 | RED | Outer beam signal |
| 4 | IR Sensor 2 OUT (Inner) | Arduino Pin D3 | BLUE | Inner beam signal |
| 5 | LCD RS | Arduino Pin D7 | PURPLE | Register select |
| 6 | LCD EN | Arduino Pin D6 | PURPLE | Enable signal |
| 7 | LCD D4 | Arduino Pin D5 | PURPLE | Data line 4 |
| 8 | LCD D5 | Arduino Pin D4 | PURPLE | Data line 5 |
| 9 | LCD D6 | Arduino Pin D12 | PURPLE | Data line 6 |
| 10 | LCD D7 | Arduino Pin D13 | PURPLE | Data line 7 |
| 11 | LCD VSS, RW, K | Arduino GND | BLACK | Ground pins |
| 12 | LCD VDD, A | Arduino 5V | YELLOW | Power pins |
| 13 | LCD V0 | Potentiometer wiper | WHITE | Contrast control |
| 14 | Buzzer (+) | Arduino Pin D8 | ORANGE | Overcapacity alert sound |
| 15 | Green LED (+) → 220Ω → | Arduino Pin D9 | GREEN | Room available indicator |
| 16 | Red LED (+) → 220Ω → | Arduino Pin D10 | RED | Room full indicator |
| 17 | Buzzer (−), LEDs (−) | Arduino GND | BLACK | Common ground |
Sensor placement tip! Mount S1 (outer) and S2 (inner) about 15–20cm apart along the direction of walking, at waist height (40–50cm from the floor) so they reliably catch each student passing through.
The Arduino Code 💻
Library needed: Install "LiquidCrystal" via Arduino IDE → Tools → Manage Libraries (it's usually pre-installed with Arduino IDE by default — search to confirm!).
// ============================================================= // 🧮 SMART CLASSROOM OCCUPANCY COUNTER // MakeMindz | Kids Arduino Project // Dual IR sensors detect entry/exit direction → // LCD shows live headcount → Buzzer warns if room is full! // ============================================================= #include <LiquidCrystal.h> // ── PIN DEFINITIONS ────────────────────────────────────── const int SENSOR_OUTER = 2; // S1 — closer to outside const int SENSOR_INNER = 3; // S2 — closer to inside const int BUZZER_PIN = 8; const int GREEN_LED = 9; const int RED_LED = 10; // LCD pins: RS, EN, D4, D5, D6, D7 LiquidCrystal lcd(7, 6, 5, 4, 12, 13); // ── SETTINGS ───────────────────────────────────────────── const int ROOM_CAPACITY = 30; // Max students allowed const long DEBOUNCE_MS = 150; // Ignore signal noise const long SEQUENCE_TIMEOUT= 1500; // Max time between S1/S2 triggers // ── STATE VARIABLES ────────────────────────────────────── int peopleCount = 0; int totalEntered = 0; int totalExited = 0; bool outerTriggered = false; bool innerTriggered = false; unsigned long outerTime = 0; unsigned long innerTime = 0; // ============================================================= // SETUP // ============================================================= void setup() { pinMode(SENSOR_OUTER, INPUT); pinMode(SENSOR_INNER, INPUT); pinMode(BUZZER_PIN, OUTPUT); pinMode(GREEN_LED, OUTPUT); pinMode(RED_LED, OUTPUT); Serial.begin(9600); lcd.begin(16, 2); lcd.print("Smart Classroom"); lcd.setCursor(0, 1); lcd.print("Counter Ready!"); delay(1500); updateDisplay(); digitalWrite(GREEN_LED, HIGH); // Room starts empty = available Serial.println("🧮 Occupancy Counter Ready!"); } // ============================================================= // LOOP // ============================================================= void loop() { int outer = digitalRead(SENSOR_OUTER); int inner = digitalRead(SENSOR_INNER); unsigned long now = millis(); // ── STEP 1: Detect outer beam break ─────────────────────── if (outer == LOW && !outerTriggered) { outerTriggered = true; outerTime = now; Serial.println("📍 S1 (outer) triggered"); } // ── STEP 2: Detect inner beam break ─────────────────────── if (inner == LOW && !innerTriggered) { innerTriggered = true; innerTime = now; Serial.println("📍 S2 (inner) triggered"); } // ── STEP 3: Both triggered? Figure out direction! ───────── if (outerTriggered && innerTriggered) { if (outerTime < innerTime) { // Outer fired first → person walked IN personEntered(); } else { // Inner fired first → person walked OUT personExited(); } resetTriggers(); } // ── STEP 4: Timeout — reset if only one sensor triggered ── if (outerTriggered && !innerTriggered && (now - outerTime > SEQUENCE_TIMEOUT)) { resetTriggers(); } if (innerTriggered && !outerTriggered && (now - innerTime > SEQUENCE_TIMEOUT)) { resetTriggers(); } } // ============================================================= // HELPER FUNCTIONS // ============================================================= void personEntered() { peopleCount++; totalEntered++; Serial.print("🟢 ENTERED — Count: "); Serial.println(peopleCount); updateDisplay(); checkCapacity(); delay(DEBOUNCE_MS); } void personExited() { if (peopleCount > 0) peopleCount--; // Never go below 0 totalExited++; Serial.print("🔴 EXITED — Count: "); Serial.println(peopleCount); updateDisplay(); checkCapacity(); delay(DEBOUNCE_MS); } void resetTriggers() { outerTriggered = false; innerTriggered = false; } void updateDisplay() { lcd.clear(); lcd.setCursor(0, 0); lcd.print("Room: "); lcd.print(peopleCount); lcd.print(" / "); lcd.print(ROOM_CAPACITY); lcd.setCursor(0, 1); if (peopleCount >= ROOM_CAPACITY) { lcd.print("Status: FULL!"); } else { lcd.print("Status: OK"); } } void checkCapacity() { if (peopleCount >= ROOM_CAPACITY) { digitalWrite(RED_LED, HIGH); digitalWrite(GREEN_LED, LOW); tone(BUZZER_PIN, 1000, 400); // Short warning beep Serial.println("🚨 ROOM FULL!"); } else { digitalWrite(RED_LED, LOW); digitalWrite(GREEN_LED, HIGH); } }
How the Code Works — Step by Step 🧠
Watching Both Sensors
The loop continuously checks both the outer (S1) and inner (S2) sensors. The moment either one detects a beam break (reads LOW), we record exactly when it happened using millis().
Comparing Trigger Times
Once BOTH sensors have triggered, we compare their timestamps. If the outer sensor's time is earlier, the person walked from outside → inside (entered). If the inner sensor's time is earlier, they walked inside → outside (exited).
Updating the Count
The personEntered() function adds 1 to peopleCount, while personExited() subtracts 1 — but never below zero, since you can't have negative people in a room!
Refreshing the LCD
updateDisplay() clears the screen and prints the current count alongside the room's maximum capacity, plus a status line that says "OK" or "FULL!".
The Capacity Alarm
checkCapacity() compares the count to ROOM_CAPACITY. If the room is full, the red LED turns on and the buzzer gives a quick warning beep — like a parking garage telling you "Lot Full"!
Timeout Safety Net
If only one sensor triggers (someone reaches in and pulls back, or a false trigger happens), we wait 1.5 seconds — if the second sensor never fires, we reset and ignore that false alarm. This keeps the count accurate!
Serial Monitor Output 📺
─────────────────────────────────────
📍 S1 (outer) triggered
📍 S2 (inner) triggered
🟢 ENTERED — Count: 1
─────────────────────────────────────
📍 S1 (outer) triggered
📍 S2 (inner) triggered
🟢 ENTERED — Count: 2
─────────────────────────────────────
📍 S2 (inner) triggered
📍 S1 (outer) triggered
🔴 EXITED — Count: 1
Mounting at the Doorway 🚪
Cut two small sensor brackets
Use cardboard or foam board to make small L-shaped brackets that can hold each IR sensor at a fixed height on either side of the door frame.
Position S1 (outer) and S2 (inner) 15–20cm apart
S1 should be closer to the outside/hallway, and S2 closer to the inside of the classroom. Both should point straight across the doorway at the same height — about waist level for kids works well.
Stick brackets to the door frame
Use double-sided tape or Blu Tack to attach each bracket to opposite sides of the door frame, so the IR beam crosses the doorway horizontally — anyone walking through will block it.
Mount the LCD where it's visible
Place the LCD display near the door, at eye level, so the teacher or students can see the live count when entering or checking the room status.
Route wires neatly along the frame
Use tape to secure wires running from the sensors back to the Arduino so nobody trips on them. Keep the Arduino board itself tucked safely on a shelf or in a small box nearby.
One person at a time works best! If two students walk through side-by-side, the sensors might only count one. For best accuracy, this works great for single-file doorways — a fun challenge is figuring out how to handle group entries as an upgrade!
Testing Your Occupancy Counter 🧪
✅ Pre-Test Checklist
Walk through from outside to inside
The LCD count should go up by 1. Serial Monitor should print "S1 triggered" then "S2 triggered" then "ENTERED — Count: 1".
Walk through from inside to outside
The count should go down by 1. You should see "S2 triggered" before "S1 triggered" this time — confirming direction detection works!
Test the capacity alarm
Temporarily lower ROOM_CAPACITY to 2 in the code, then walk in twice. The red LED and buzzer should trigger on the second entry!
Test with multiple people
Have a few classmates walk through one at a time. Watch the count rise and fall accurately. Celebrate — your smart classroom counter works! 🎉
Troubleshooting Guide 🔧
❓ Count doesn't change at all
Check both sensor OUT pins are connected to D2 and D3. Open Serial Monitor — do you see "S1 triggered" and "S2 triggered" messages when you wave a hand through the beams?
❓ Count goes up even when exiting
Your sensors might be swapped! Check that S1 (outer, closer to outside) is wired to D2, and S2 (inner, closer to inside) is wired to D3. Swap the pin numbers in code if needed.
❓ LCD shows nothing or garbled text
Adjust the potentiometer connected to LCD V0 pin — this controls contrast. Also double-check all 6 LCD data/control pins (RS, EN, D4-D7) match the code's LiquidCrystal() pin order.
❓ Count sometimes skips by 2 or misses people
This usually means two people walked through close together, or too fast. Try widening the gap between S1 and S2 slightly, or remind students to walk through one at a time for accurate counting.
❓ False triggers happen randomly
Bright sunlight or fluorescent lights can interfere with IR sensors. Try shielding sensors with a small cardboard hood, or adjust the sensitivity trimmer (small blue potentiometer) on the sensor module itself.

Comments
Post a Comment