Smart Car Parking System using Arduino, ESP8266 NodeMCU and Blynk server.

Smart Car parking system using Arduino and ESP8266 NodeMCU

A smart car parking system helps in solving a common challenge of finding parking space in areas with a lot of traffic like residential areas, office buildings, schools and other facilities. In this tutorial I will demonstrate how a smart car parking system can be made using Arduino, ESP8266 NodeMCU and Blynk server.

This system enables car drivers to monitor parking slots on a mobile device like a smart phone so that they can know which parking slots are available within a given location. A driver will not waste time going to a parking lot that is full there by avoiding congestion of cars due to lack of parking areas which consequently improves the overall flow of traffic.

Hardware Components needed in making a smart car parking system.

  • Servo motors used to simulate movement of the toll gates at the entrance and exit of the parking
  • IR sensors for detecting the presence of objects, in this case they detect whether a car has occupied a specific slot. The signal from these sensors is sent to the microcontroller
  • Arduino board based on ATMega328 AVR microcontroller acts as the major control device for reading signals from the IR sensors and motors and connecting the parking lot to the WiFi device.
  • ESP8266 NodeMCU WiFi module for connecting the parking lot to a cloud service so that we can be able to access the parking lot over the internet using a mobile phone application.

Schematic of the smart car parking system using Arduino and ESP8266 NodeMCU.

I have divided the parking into two lots with each parking having three parking slots. These slots have IR sensors attached to digital pins 4,5,6,7,8 and 9 of Arduino. Two other IR sensors are placed at the entrance and exit of the parking and attached to Arduino digital pins 11 and 12.

Two servo motors are used to move toll gates at the entrance and exit and these are attached to Arduino digital pins 3 and 13.   

smart car parking system using Arduino and ESP8266 NodeMCU schematic

Communication between the Arduino board and ESP8266 NodeMCU is achieved through serial pins TR and RX of NodeMCU connected to Pins 0 and 2 of Arduino Uno respectively. In case you are using a different Arduino board make sure you use the correct serial pins.

Power supply considerations.

The servo motors, Arduino board and ESP8266 NodeMCU should all be supplied with separate 5V power supplies. Also make sure that all the components are properly grounded.

How the smart car parking system works.

The IR sensor at the entrance toll gate detects a coming car and will automatically open whenever there is a free slot in the parking lot but if the lot is full, then the gate will not open.

A simple mobile app is designed using Blynk server to show the driver the occupied and empty slots in the parking lot where Esp8266 NodeMCU enables the communication between the sensors in the parking lot and any mobile device via a network cloud service in this case I have used Blynk server.

Code for smart car parking system using Arduino and ESP8266 NodeMCU.

The code for this project is divided into two parts, one part for controlling the Arduino board and the other code is for controlling the ESP8266 NodeMCU connection with the Blynk server. However, both of these code snippets are written using Arduino IDE.

Before proceeding with the code you can make reference on how to interface servo motor, IR sensors and ESP8266 NodeMCU with Arduino using the links below;

Code for the Arduino Board

This code mainly contains declaration for the IR sensors and servo motors and also includes conditions for controlling the opening and closing of the entrance and exit gate with depending on the situation of the parking lot.  

The SoftwareSerial.h library is included to enable serial communication with the ESP8266 NodeMCU.

#include <SoftwareSerial.h>
#include <Servo.h>

Servo myservo1;  // create servo object to control a servo
Servo myservo2;

SoftwareSerial nodemcu(0,1);

int parking1_slot1_ir_s = 4; // parking slot1 infrared sensor connected with pin number 4 of arduino
int parking1_slot2_ir_s = 5;
int parking1_slot3_ir_s = 6;

int parking2_slot1_ir_s = 7;
int parking2_slot2_ir_s = 8;
int parking2_slot3_ir_s = 9;

int entrance_gate = 11;
int exit_gate = 12;

int pos1 = 90;    // variable to store the servo position(entrance gate)
int pos2 = 90;    // exit gate

String sensor1; 
String sensor2; 
String sensor3; 
String sensor4; 
String sensor5; 
String sensor6; 


String cdata =""; // complete data, consisting of sensors values

void setup()
{
Serial.begin(9600); 
nodemcu.begin(9600);

pinMode(parking1_slot1_ir_s, INPUT);
pinMode(parking1_slot2_ir_s, INPUT);
pinMode(parking1_slot3_ir_s, INPUT);

pinMode(parking2_slot1_ir_s, INPUT);
pinMode(parking2_slot2_ir_s, INPUT);
pinMode(parking2_slot3_ir_s, INPUT);

pinMode(entrance_gate, INPUT);
pinMode(exit_gate, INPUT);

myservo1.attach(13);  // attaches the servo on pin 9 to the servo object
myservo2.attach(3);


}

void loop()
{

p1slot1(); 
p1slot2();
p1slot3(); 

p2slot1();
p2slot2();
p2slot3();

gates();
//conditions();

  
  
   cdata = cdata + sensor1 +"," + sensor2 + ","+ sensor3 +","+ sensor4 + "," + sensor5 + "," + sensor6 +","; // comma will be used a delimeter
   Serial.println(cdata); 
   nodemcu.println(cdata);
   delay(6000); // 100 milli seconds
   cdata = ""; 
digitalWrite(parking1_slot1_ir_s, HIGH); 
digitalWrite(parking1_slot2_ir_s, HIGH); 
digitalWrite(parking1_slot3_ir_s, HIGH);

digitalWrite(parking2_slot1_ir_s, HIGH);
digitalWrite(parking2_slot2_ir_s, HIGH);
digitalWrite(parking2_slot3_ir_s, HIGH);

digitalWrite(entrance_gate, HIGH);
digitalWrite(exit_gate, HIGH);
}


void p1slot1() // parkng 1 slot1
{
  if( digitalRead(parking1_slot1_ir_s) == LOW) 
  {
  sensor1 = "255";
 delay(200); 
  } 
if( digitalRead(parking1_slot1_ir_s) == HIGH)
{
  sensor1 = "0";  
 delay(200);  
}

}

void p1slot2() // parking 1 slot2
{
  if( digitalRead(parking1_slot2_ir_s) == LOW) 
  {
  sensor2 = "255"; 
  delay(200); 
  }
if( digitalRead(parking1_slot2_ir_s) == HIGH)  
  {
  sensor2 = "0";  
 delay(200);
  } 
}


void p1slot3() // parking 1 slot3
{
  if( digitalRead(parking1_slot3_ir_s) == LOW) 
  {
  sensor3 = "255"; 
  delay(200); 
  }
if( digitalRead(parking1_slot3_ir_s) == HIGH)  
  {
  sensor3 = "0";  
 delay(200);
  } 
}


// now for parking 2

void p2slot1() // parking 1 slot3
{
  if( digitalRead(parking2_slot1_ir_s) == LOW) 
  {
  sensor4 = "255"; 
  delay(200); 
  }
if( digitalRead(parking2_slot1_ir_s) == HIGH)  
  {
  sensor4 = "0";  
 delay(200);
  } 
}


void p2slot2() // parking 1 slot3
{
  if( digitalRead(parking2_slot2_ir_s) == LOW) 
  {
  sensor5 = "255"; 
  delay(200); 
  }
if( digitalRead(parking2_slot2_ir_s) == HIGH)  
  {
  sensor5 = "0";  
 delay(200);
  } 
}


void p2slot3() // parking 1 slot3
{
  if( digitalRead(parking2_slot3_ir_s) == LOW) 
  {
  sensor6 = "255"; 
  delay(200); 
  }
if( digitalRead(parking2_slot3_ir_s) == HIGH)  
  {
  sensor6 = "0";  
 delay(200);
  } 
}

// for the gates

void gates()
{
  if (digitalRead(exit_gate) == LOW)
      {
        for (pos2 = 90; pos2 <= 180 ; pos2 += 1) { // goes from 0 degrees to 180 degrees
          // in steps of 1 degree
          myservo2.write(pos2);              // tell servo to go to position in variable 'pos'
          delay(15);                       // waits 15ms for the servo to reach the position
        }
          delay(1000);
        for (pos2 = 180; pos2 >= 90; pos2 -= 1) { // goes from 180 degrees to 0 degrees
          myservo2.write(pos2);              // tell servo to go to position in variable 'pos'
          delay(15);                       // waits 15ms for the servo to reach the position
        }
      }
  
  if (((digitalRead(entrance_gate) == LOW)) && (( digitalRead(parking1_slot1_ir_s) == HIGH) || ( digitalRead(parking1_slot2_ir_s) == HIGH) || ( digitalRead(parking1_slot3_ir_s) == HIGH) || ( digitalRead(parking2_slot1_ir_s) == HIGH) || ( digitalRead(parking2_slot2_ir_s) == HIGH)|| ( digitalRead(parking2_slot3_ir_s) == HIGH)))
      {
        for (pos1 = 0; pos1 <= 90 ; pos1 += 1) { // goes from 0 degrees to 180 degrees
          // in steps of 1 degree
          myservo1.write(pos1);              // tell servo to go to position in variable 'pos'
          delay(15);                       // waits 15ms for the servo to reach the position
        }
          delay(1000);
        for (pos1 = 90; pos1 >= 0; pos1 -= 1) { // goes from 180 degrees to 0 degrees
          myservo1.write(pos1);              // tell servo to go to position in variable 'pos'
          delay(15);                       // waits 15ms for the servo to reach the position
        }
      }


}

Code for ESP8266 NodeMCU

This code enables communication between the ESP8266 NodeMCU with Arduino and with the Blynk server.

You need to enter the correct WiFi SSID and password and the unique ‘AuthToken’ that allows the device to access the Blynk server.

#define BLYNK_PRINT Serial

#include <ESP8266WiFi.h>
#include <BlynkSimpleEsp8266.h>
#include <SoftwareSerial.h>
#include <SimpleTimer.h>

SoftwareSerial arduinoUno(0,1); //( RX, TX )

char auth[] = "enter unique AuthToken";

// Your WiFi credentials.
char ssid[] = "enter WiFi ssid";
char pass[] = "enter WiFi password";

SimpleTimer timer;

String myString; // complete message from arduino, which consists of sensors data
char rdata; // received characters

int firstVal, secondVal,thirdVal; // sensors 
int led1,led2,led3,led4,led5,led6;
// This function sends Arduino's up time every second to Virtual Pin (1).
// In the app, Widget's reading frequency should be set to PUSH. This means
// that you define how often to send data to Blynk App.
void myTimerEvent()
{
  // You can send any value at any time.
  // Please don't send more that 10 values per second.
  Blynk.virtualWrite(V1, millis() / 1000);
  
}

void setup()
{
  // Debug console
  Serial.begin(9600);

  Blynk.begin(auth, ssid, pass);

    timer.setInterval(1000L,sensorvalue1); 
    timer.setInterval(1000L,sensorvalue2); 
    timer.setInterval(1000L,sensorvalue3);
    timer.setInterval(1000L,sensorvalue4);
    timer.setInterval(1000L,sensorvalue5);
    timer.setInterval(1000L,sensorvalue6);
  

}

void loop()
{
   if (Serial.available() == 0 ) 
   {
  Blynk.run();
  timer.run(); // Initiates BlynkTimer
   }
   
  if (Serial.available() > 0 ) 
  {
    rdata = Serial.read(); 
    myString = myString+ rdata; 
    //Serial.print(rdata);
    if( rdata == '\n')
    {
     Serial.println(myString); 
  // Serial.println("fahad");
// new code
String l = getValue(myString, ',', 0);
String m = getValue(myString, ',', 1);
String n = getValue(myString, ',', 2);
String o = getValue(myString, ',', 3);
String p = getValue(myString, ',', 4);
String q = getValue(myString, ',', 5);


// these leds represents the leds used in Blynk application
led1 = l.toInt();
led2 = m.toInt();
led3 = n.toInt();
led4 = o.toInt();
led5 = p.toInt();
led6 = q.toInt();

  myString = "";
// end new code
    }
  }

}

void sensorvalue1()
{
int sdata = led1;
  // You can send any value at any time.
  // Please don't send more that 10 values per second.
  Blynk.virtualWrite(V10, sdata);

}
void sensorvalue2()
{
int sdata = led2;
  // You can send any value at any time.
  // Please don't send more that 10 values per second.
  Blynk.virtualWrite(V11, sdata);

}

void sensorvalue3()
{
int sdata = led3;
  // You can send any value at any time.
  // Please don't send more that 10 values per second.
  Blynk.virtualWrite(V12, sdata);

}

void sensorvalue4()
{
int sdata = led4;
  // You can send any value at any time.
  // Please don't send more that 10 values per second.
  Blynk.virtualWrite(V13, sdata);

}

void sensorvalue5()
{
int sdata = led5;
  // You can send any value at any time.
  // Please don't send more that 10 values per second.
  Blynk.virtualWrite(V14, sdata);

}

void sensorvalue6()
{
int sdata = led6;
  // You can send any value at any time.
  // Please don't send more that 10 values per second.
  Blynk.virtualWrite(V15, sdata);

}


String getValue(String data, char separator, int index)
{
    int found = 0;
    int strIndex[] = { 0, -1 };
    int maxIndex = data.length() - 1;

    for (int i = 0; i <= maxIndex && found <= index; i++) {
        if (data.charAt(i) == separator || i == maxIndex) {
            found++;
            strIndex[0] = strIndex[1] + 1;
            strIndex[1] = (i == maxIndex) ? i+1 : i;
        }
    }
    return found > index ? data.substring(strIndex[0], strIndex[1]) : "";
}

Blynk Application

This is used to remotely monitor the state of the parking lot from an Android or IOS device.

The Application is designed with simple LEDs that turn ON to indicate an occupied slot and OFF for an empty slot as demonstrated below.

Blynk App for smart car parking system

In the above example, all the three slots in parking 1 are occupied while parking 2 has the middle slot empty.