🅿️ پارکینگ هوشمند با آردوینو: دو سنسور اولتراسونیک، راهبند سروو و نمایش جای خالی روی LCD

✍️ تیم ووکوی فارسی ·

در این پروژه یک پارکینگ هوشمند با آردوینو می‌سازیم: ماشین که جلوی ورودی آمد، اگر جای خالی باشد راهبند بالا می‌رود و بعد از عبور ماشین پایین می‌آید و یک جا از ظرفیت کم می‌شود. هنگام خروج برعکس. تعداد جای خالی همیشه روی LCD دیده می‌شود، چراغ سبز و قرمز وضعیت را نشان می‌دهند و اگر پارکینگ پر باشد، بوق می‌زند و در باز نمی‌شود. این پروژه برای نمایشگاه مدرسه و پروژه‌ی دانشجویی محبوب است و همه‌اش را می‌شود اول در شبیه‌ساز آردوینو ساخت.

ایده‌ی اصلی: تشخیص جهت با دو سنسور

یک سنسور بیرون راهبند است و یکی داخل آن. ماشینی که وارد می‌شود اول سنسور بیرون و بعد سنسور داخل را فعال می‌کند؛ ماشینی که خارج می‌شود برعکس. برنامه سه حالت دارد:

شمارش فقط وقتی انجام می‌شود که ماشین واقعاً از سنسور آن طرف رد شده باشد و هر دو سنسور ۱٫۵ ثانیه خالی بمانند. اگر راننده جلوی در آمد و دور زد، بعد از ده ثانیه راهبند بدون شمارش بسته می‌شود.

قطعه‌ها

سیم‌کشی

قطعهپایهبه آردوینو
اولتراسونیک بیرون (ورودی)+ / TRIG / ECHO / −5V / D4 / D5 / GND
اولتراسونیک داخل (خروجی)+ / TRIG / ECHO / −5V / D6 / D7 / GND
بازر+ / −D8 / GND
سروو+ (قرمز) / − (قهوه‌ای) / SIG (نارنجی)5V / GND / D9
LED سبزپایه‌ی بلند از راه ۲۲۰ اهمD11؛ پایه‌ی کوتاه به GND
LED قرمزپایه‌ی بلند از راه ۲۲۰ اهمD12؛ پایه‌ی کوتاه به GND
LCD I2CGND / VCC / SDA / SCLGND / 5V / A4 / A5

کد کامل

// Smart parking: entry and exit HC-SR04 sensors, a servo barrier,
// an I2C LCD showing free spaces, two LEDs and a buzzer.
#include <Wire.h>
#include <LiquidCrystal_I2C.h>
#include <Servo.h>

const int IN_TRIG = 4, IN_ECHO = 5;     // sensor outside the gate
const int OUT_TRIG = 6, OUT_ECHO = 7;   // sensor inside the gate
const int BUZZER = 8;
const int SERVO_PIN = 9;
const int GREEN_LED = 11, RED_LED = 12;

const int CAPACITY = 4;                 // parking spaces
const int CAR_CM = 15;                  // closer than this = a car is there
const int GATE_CLOSED = 0, GATE_OPEN = 90;
const unsigned long CLEAR_MS = 1500;    // both sensors clear this long = car has passed
const unsigned long GIVE_UP_MS = 10000; // close the gate if the car turns back

LiquidCrystal_I2C lcd(0x27, 16, 2);
Servo gate;

enum Mode { IDLE, ENTERING, EXITING };
Mode mode = IDLE;
int freeSpaces = CAPACITY;
bool passed = false;
unsigned long openedAt = 0, lastSeen = 0, lastFull = 0;

long readCm(int trig, int echo) {
  digitalWrite(trig, LOW);
  delayMicroseconds(2);
  digitalWrite(trig, HIGH);
  delayMicroseconds(10);
  digitalWrite(trig, LOW);
  long us = pulseIn(echo, HIGH, 30000);   // wait at most 30 ms
  if (us == 0) return 999;                // no echo = nothing in front
  return us / 58;                         // microseconds -> cm
}

void showLine(int row, String text) {
  while (text.length() < 16) text += " ";   // pad to wipe old characters
  lcd.setCursor(0, row);
  lcd.print(text);
}

void showSpaces() {
  showLine(0, "Free: " + String(freeSpaces) + "/" + String(CAPACITY));
  showLine(1, freeSpaces > 0 ? "Welcome" : "FULL");
}

void openGate(Mode m) {
  mode = m;
  passed = false;
  openedAt = millis();
  lastSeen = millis();
  gate.write(GATE_OPEN);
  tone(BUZZER, 1500, 120);
  showLine(1, m == ENTERING ? "Gate open: IN" : "Gate open: OUT");
  Serial.println(m == ENTERING ? "Car entering" : "Car leaving");
}

void closeGate() {
  gate.write(GATE_CLOSED);
  mode = IDLE;
  showSpaces();
  Serial.print("Free spaces: ");
  Serial.println(freeSpaces);
}

void setup() {
  Serial.begin(9600);
  pinMode(IN_TRIG, OUTPUT);
  pinMode(IN_ECHO, INPUT);
  pinMode(OUT_TRIG, OUTPUT);
  pinMode(OUT_ECHO, INPUT);
  pinMode(GREEN_LED, OUTPUT);
  pinMode(RED_LED, OUTPUT);
  gate.attach(SERVO_PIN);
  gate.write(GATE_CLOSED);
  lcd.init();
  lcd.backlight();
  showSpaces();
}

void loop() {
  bool atIn = readCm(IN_TRIG, IN_ECHO) < CAR_CM;
  delay(20);                              // let the first echo fade away
  bool atOut = readCm(OUT_TRIG, OUT_ECHO) < CAR_CM;
  unsigned long now = millis();

  if (mode == IDLE) {
    if (atIn) {
      if (freeSpaces > 0) {
        openGate(ENTERING);
      } else if (now - lastFull > 3000) { // full: beep, but not on every loop
        lastFull = now;
        showLine(1, "FULL - sorry");
        tone(BUZZER, 400, 400);
      }
    } else if (atOut) {
      openGate(EXITING);
    }
  } else {
    bool farSide = (mode == ENTERING) ? atOut : atIn;   // the sensor past the gate
    if (farSide) passed = true;
    if (atIn || atOut) lastSeen = now;
    bool allClear = now - lastSeen >= CLEAR_MS;
    if (passed && allClear) {
      if (mode == ENTERING) freeSpaces--;
      else if (freeSpaces < CAPACITY) freeSpaces++;
      closeGate();
    } else if (!passed && allClear && now - openedAt > GIVE_UP_MS) {
      closeGate();                          // the driver turned back: no count
    }
  }

  digitalWrite(GREEN_LED, freeSpaces > 0 ? HIGH : LOW);
  digitalWrite(RED_LED, freeSpaces > 0 ? LOW : HIGH);
  delay(50);
}

توضیح بخش‌های مهم

قدم‌به‌قدم در شبیه‌ساز

  1. اول فقط دو سنسور را بچین و با سریال مانیتور مطمئن شو هر کدام فاصله‌ی درست می‌دهد. پروژه‌ی آماده‌ی فاصله‌سنج برای این مرحله کافی است.
  2. سروو را اضافه کن و با یک برنامه‌ی کوچک ۰ و ۹۰ درجه را امتحان کن تا جهت باز و بسته شدن را بشناسی.
  3. LCD را وصل کن و کد کامل را اجرا کن. باید «Free: 4/4» و «Welcome» ببینی.
  4. فاصله‌ی سنسور بیرون را زیر ۱۵ سانتی‌متر ببر: راهبند باز می‌شود. حالا فاصله‌ی سنسور بیرون را زیاد و سنسور داخل را کم کن (ماشین رد شد) و بعد آن را هم زیاد کن. بعد از ۱٫۵ ثانیه راهبند بسته می‌شود و «Free: 3/4» می‌آید.
  5. چهار بار این کار را تکرار کن تا پارکینگ پر شود؛ LED قرمز روشن می‌شود و در دیگر باز نمی‌شود.
  6. خروج را با سنسور داخل امتحان کن و ببین شمارنده بالا می‌رود.

آردوینو اونو، سنسور اولتراسونیک و سروو در تینکرکد فارسی رایگان‌اند. LCD I2C جزو ماژول‌های حرفه‌ای است و برای اجرایش اشتراک Plus لازم است؛ اگر نداری، سه خط lcd را حذف کن و پیام‌ها را در سریال مانیتور ببین. برای تمرین با یک سنسور، درس سنسور پارک و پروژه‌ی سنسور پارک را ببین.

ساخت ماکت واقعی

اشکال‌های رایج

ایده برای کامل‌تر کردن

تعداد جای خالی را در EEPROM ذخیره کن تا با قطع برق پاک نشود. برای هر جای پارک یک سنسور جدا بگذار و روی LCD نشان بده کدام جا خالی است. یا پروژه را به ESP32 ببر و ظرفیت را در یک صفحه‌ی وب نشان بده؛ ایده‌اش در ۳۰ ایده پروژه اینترنت اشیا و راه ساختن صفحه‌اش در وب‌سرور ESP32 است. برای حرکت نرم‌تر راهبند، آموزش سروو با آردوینو را ببین.

پارکینگ هوشمند را در تینکرکد فارسی بساز 🅿️

سؤال‌های رایج

چرا دو سنسور لازم است و یکی کافی نیست؟

با یک سنسور نمی‌شود فهمید ماشین وارد شد یا خارج، یا جلوی در آمد و دور زد. ترتیب دیده شدن ماشین در دو سنسورِ دو طرف راهبند، جهت حرکت را مشخص می‌کند و شمارش را درست نگه می‌دارد.

اگر اشتراک Plus نداشته باشم، این پروژه در شبیه‌ساز اجرا می‌شود؟

آردوینو اونو، سنسور اولتراسونیک و سروو رایگان‌اند. LCD I2C جزو ماژول‌های حرفه‌ای است؛ می‌توانی خط‌های LCD را حذف کنی و همان پیام‌ها را در سریال مانیتور ببینی، یا از LCD معمولی با کتابخانه‌ی LiquidCrystal استفاده کنی.

برای ماکت واقعی از چه سنسوری استفاده کنم؟

برای ماکت کوچک، سنسور اولتراسونیک HC-SR04 یا ماژول مادون قرمز تشخیص مانع هر دو جواب می‌دهند. اولتراسونیک فاصله را عددی می‌دهد و آستانه‌اش در کد تنظیم می‌شود؛ مادون قرمز ارزان‌تر و کوچک‌تر است ولی به رنگ و نور حساس است.

مقاله‌های مرتبط

💡

۳۰ ایده پروژه اینترنت اشیا با ESP32، از مبتدی تا پیشرفته (با قطعه‌ها و نقطه‌ی شروع)

🎓

پروژه پایانی دانشگاه با میکروکنترلر: از انتخاب موضوع تا دفاع (برای دانشجوی برق، کامپیوتر و مکاترونیک)

🏫

پروژه مدرسه با آردوینو: ایده‌های مناسب هر سن، ارائه در جشنواره و نمایشگاه علمی، و نکته‌های ایمنی

🧩

ساخت API با JSON روی ESP32 با کتابخانه‌ی ArduinoJson

همه‌ی آموزش‌های پروژه‌ها و ایده‌ها ← · همه‌ی مقاله‌ها