Bidirectional Visitor counter using Arduino and Ultrasonic Sensors, Counting Visitors
Table of Contents
Visitor counter using Arduino:
Visitor counter using Arduino and Ultrasonic Sensors- In this article we are going to make a bidirectional visitors counting system using Arduino, a pair of Ultrasonic Sensors, and an Oled display module. The Arduino visitors counter will help us in maintaining the number of people who go in and out of a venue or a shop and maintain a maximum limit on the number of people inside it and hence help to maintain social distancing and reduce the transmission of covid-19. So let’s get started so as you can see in the poster here there are a number of people waiting outside the shop and at the door there’s a device and that is the device we are going to make it, a visitors counter and it counts the number of people going in or out of the shop or the venue and that’s exactly what we are going to make. Counting visitors can be quite handy in situation when you need to keep track of all the visitors inside a building, room, or any place. Counting visitors can be implemented using different techniques, you can also make the same visitor counting system using IR sensors, But the reason I am using Ultrasonic sensor is that it’s detection range is higher than the IR Sensors. You can also implement the same version of the Visitor counting system using PLC which I have already done.
Components Required:
Now for designing a visitors counter we will require the following components:
- Arduino UNO
- Ultrasonic sensor
- OLED display
- Buzzer
- Jumper wires
Amazon Links:
Arduino Nano USB-C Type (Recommended)
SSD1306 128×64 Oled i2c display Module
*Disclosure: These are affiliate links. As an Amazon Associate I earn from qualifying purchases.
Visitor Counting System Circuit diagram:
Now first of all we will connect the OLED display module with the Arduino Uno
- Connect the SDA pin of the OLED display with analog pin A4
- Connect the SCK pin of the OLED with the analog pin A5
- Connect the ground of the OLED with the ground of the Arduino
- Connect the VCC of the OLED with 5V of the Arduino
The type of the Oled display module i am using is I2C. There are different types of the Oled display module, so if you are not able to see any text on the Oled display then read my article on “how to use the Oled display module with Arduino, and how to fix the most common issues”. Now after interfacing the I2C supported OLED display module, we will connect the ultrasonic sensors with the Arduino.
- Connect the VCC of both the Ultrasonic sensors with 5V.
- Similarly, connect the ground of both the Ultrasonic sensors with ground of the Arduino.
- Connect the echo pin of the ultrasonic sensor 1 with the digital pin 9.
- Connect the trig pin of the ultrasonic sensor 1 with digital pin 8.
- Connect the echo pin of the ultrasonic sensor 2 with the digital pin 7.
- Connect the trig pin of the ultrasonic sensor 2 with digital pin 6.
Use of the Visitor Counting System:
This project can be used for social distancing to maintain a distance between people and make sure that there’s not too much crowd.
The second is crowd management because even without COVID it’s not healthy to have too many people inside premises. So crowd management is another use.
Future use of the Visitor Counter system:
In the future you could also integrate this circuit with fans or tube lights and other such electronic equipment inside the shop or office and by doing so you can automate the device and save electricity as well. You can check if there is someone inside the room or shop and then turn ON the lights automatically, and when there is no one inside the controller will automatically turn OFF the loads.
Before, you start the programming; first of all, make sure you download all the necessary libraries.
Visitor Counter complete code:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 |
<span style="font-size: 14pt; font-family: 'times new roman', times, serif;">#include <Adafruit_SSD1306.h> #include <Wire.h> #include <Adafruit_GFX.h> #define SCREEN_WIDTH 128 #define SCREEN_HEIGHT 64 int buzzerPin = 6; int trigPin1 = 8; int echoPin1 = 9; int trigPin2 = 10; int echoPin2 = 11; String sequence = ""; int timeoutCounter = 0; int currentPeople = 0; int maxPeople = 5; Adafruit_SSD1306 display(SCREEN_WIDTH,SCREEN_HEIGHT, &Wire, -1); void displayText(String txt){ display.clearDisplay(); display.setTextSize(3); display.setTextColor(WHITE); display.setCursor(0,0); display.print(txt); display.display(); } int distance1, distance2, initialDistance1, initialDistance2; int measureDistance(int trigPin, int echoPin){ digitalWrite(trigPin, HIGH); delayMicroseconds(10); digitalWrite(trigPin, LOW); int duration = pulseIn (echoPin, HIGH); return (duration/2) / 29.1; } void setup() { display.begin(SSD1306_SWITCHCAPVCC, 0x3C); displayText("Visitor Counter"); pinMode(buzzerPin, OUTPUT); // declare piezo as output pinMode(trigPin1, OUTPUT); pinMode(echoPin1, INPUT); pinMode(trigPin2, OUTPUT); pinMode(echoPin2, INPUT); Serial.begin(9600); //initial readings initialDistance1 = measureDistance(trigPin1, echoPin1); initialDistance2 = measureDistance(trigPin2, echoPin2); } void loop(){ delay(200);// reading will be taken after 200 milliseconds distance1 = measureDistance(trigPin1, echoPin1); distance2 = measureDistance(trigPin2, echoPin2); //Process the data if(distance1 < initialDistance1 - 30 && sequence.charAt(0) != '1'){ sequence += "1"; }else if(distance2 < initialDistance2 - 30 && sequence.charAt(0) != '2'){ sequence += "2"; } if(sequence.equals("12")){ currentPeople++; sequence=""; delay(550); }else if(sequence.equals("21") && currentPeople > 0){ currentPeople--; sequence=""; delay(550); } //Resets the sequence if it is invalid or timeouts if(sequence.length() > 2 || sequence.equals("11") || sequence.equals("22") || timeoutCounter > 200){ sequence=""; } if(sequence.length() == 1){ // timeoutCounter++; }else{ timeoutCounter=0; } //Print values to serial Serial.print("Seq: "); Serial.println(sequence); Serial.print("S1: "); Serial.println(distance1); Serial.print("S2: "); Serial.println(distance2); Serial.print("Current people: "); Serial.println(currentPeople); displayText(String(currentPeople)); //If the number of people is high, trigger the buzzer if(currentPeople > maxPeople){ tone(buzzerPin, 1, 500); displayText(String(currentPeople)); }else{ noTone(buzzerPin); } } </span> |
Visitors Counter Project Code Explanation:
Let’s start coding according to the circuit. We have two ultrasonic sensors, one buzzer, and one display. So let’s start with the ultrasonic sensor and buzzer for now and then add the display later. We have defined which pins are attached to which components. So let’s start with the buzzer which is connected to the pin6 of the Arduino.
1 |
<span style="font-size: 18pt; font-family: 'times new roman', times, serif;">int buzzerPin = 6;</span> |
The ultrasonic sensor have two pins one is the trigger and one is the echo so for the first ultrasonic sensor we have a trigger pin attached to eight and echo pin attached to nine and similarly for the second one we have 6 and 7.
1 2 3 4 5 6 7 8 9 |
<span style="font-size: 18pt; font-family: 'times new roman', times, serif;">int buzzerPin = 6; int trigPin1 = 8; int echoPin1 = 9; int trigPin2 = 6; int echoPin2 = 7;</span> |
We declare some integers so that we have predefined the maximum number of people has five and current number of people
1 2 3 4 5 |
<span style="font-size: 18pt; font-family: 'times new roman', times, serif;">int timeoutCounter = 0; int currentPeople = 0; int maxPeople = 5;</span> |
Now we go into the setup and we explicitly tell which pin is for the output and which pin is for the input. So we have defined
1 2 3 4 5 6 7 8 9 |
<span style="font-size: 18pt; font-family: 'times new roman', times, serif;">pinMode(buzzerPin, OUTPUT); // declare piezo as output pinMode(trigPin1, OUTPUT); pinMode(echoPin1, INPUT); pinMode(trigPin2, OUTPUT); pinMode(echoPin2, INPUT);</span> |
So basically, how the ultrasonic sensor works is it sends a trigger or it sends an ultrasound wave and it waits for the wave to be reflected back and when it’s reflected back it is taken in by the echo. So that is how it works and that’s why the trig is output and echo is input. The buzzer pin will be output, because we are sending a signal from the Arduino to the buzzer for the buzzer to ring. So, the ultrasonic sensor basically will measure the distance between itself and any possible obstacle. So at first we want to place the sensors and then find the initial distance between it and any other maybe the other side of the door or something like that so for that we calculate the initial distance and that comes into the setup function and in the loop function which is constantly called again and again in that we will keep measuring the distance to any possible other people that comes. So let’s do that also serial.begin will be done so initial distance from the first sensor and similarly initial distance for the second one.
1 2 3 |
<span style="font-size: 18pt; font-family: 'times new roman', times, serif;">initialDistance1 = measureDistance(trigPin1, echoPin1); initialDistance2 = measureDistance(trigPin2, echoPin2);</span> |
In the loop function we make a delay of 200 microseconds this will actually help because every time the loop function is done there will be a delay of 200 microseconds so that the device is not over using itself.
1 |
<span style="font-size: 18pt; font-family: 'times new roman', times, serif;">delay(200);</span> |
Then we will copy the above distances and paste it in the loop function.
1 2 3 |
<span style="font-size: 18pt; font-family: 'times new roman', times, serif;">initialDistance1 = measureDistance(trigPin1, echoPin1); initialDistance2 = measureDistance(trigPin2, echoPin2);</span> |
We will define the measure distance function it will take in a trigger pin number and an echo pin number. So basically we make the trigger pin on high and then we let it do that for 10 microseconds and make it low again and when it is reflected and it comes back it is taken in through the echo pin.
In the measureDistance function we will write the command
1 2 3 4 5 6 7 8 9 10 11 12 13 |
<span style="font-size: 18pt; font-family: 'times new roman', times, serif;">int measureDistance(int trigPin, int echoPin){ digitalWrite(trigPin, HIGH); delayMicroseconds(10); digitalWrite(trigPin, LOW); int duration = pulseIn (echoPin, HIGH); return (duration/2) / 29.1; }</span> |
So when we put echo pin on high and get the input from there, we get a duration the way we get it is that the trigger i mean the ultrasound wave is first passed and when it comes it is reflecting back the amount of time that it takes to reflect back is recorded as duration and from the duration we can get the distance. So the duration is divided by 2 and then divided by 29.1 to get the distance and then the distance is returned and that’s how we get the initial distance.
Now the next thing is how we will know if a person is entering or exiting those premises the way we do it and that’s why we use two ultrasonic sensors. If the first ultrasound sensor is triggered first and then the second one is triggered that means a person is going in and the counter is incremented whereas if a person is exiting then the second one is triggered and then the first one. So that’s how we know whether a person is entering or exiting.
In the code the way we do it is by using a sequence. So a sequence is just a string an empty string if the first one is triggered then the sequence becomes one. If the second one is triggered the sequence is concatenated and becomes one two so if the sequence is 1 and 2 a person is entering if the sequence is 2 and 1 then a person is leaving.
1 |
<span style="font-size: 18pt; font-family: 'times new roman', times, serif;">String sequence = "";</span> |
So we write this in the loop function if the distance is less than the initial distance minus 30 then the sequence is concatenated with one also the sequence had the first character should not be one initially.
1 2 3 4 5 |
<span style="font-size: 18pt; font-family: 'times new roman', times, serif;">if(distance1 < initialDistance1 - 30 && sequence.charAt(0) != '1'){ sequence += "1"; }</span> |
Similarly else if the distance of the second sensor is less than the initial distance of it minus 30 and that character that sequence does not have two already in the sequence then it is concatenated with two.
1 2 3 4 5 |
<span style="font-size: 18pt; font-family: 'times new roman', times, serif;">else if(distance2 < initialDistance2 - 30 && sequence.charAt(0) != '2'){ sequence += "2"; }</span> |
So if the sequence equals 1 2 then the number of current people are incremented and the sequence becomes empty again and there’s a delay of 550 microseconds
1 2 3 4 5 6 7 |
<span style="font-size: 18pt; font-family: 'times new roman', times, serif;"> if(sequence.equals("12")){ currentPeople++; sequence=""; delay(550);</span> |
Else if the sequence equals 2 1 and the current people is greater than 0 then the counter is decrement that is if there are already 0 people inside the premises then you can’t really decrement it. So that is why the second condition is there and same thing the current people are decremented and the sequence is is made empty and it is delayed by 550 microseconds.
1 2 3 4 5 6 7 8 9 |
<span style="font-size: 18pt; font-family: 'times new roman', times, serif;">else if(sequence.equals("21") && currentPeople > 0){ currentPeople--; sequence=""; delay(550); }</span> |
If the sequence is 11 or 22 or if the timeout counter is greater than 200 if the second sensor has not been triggered but the first sensor has been triggered and time out counter is greater than 200.
1 2 3 4 5 6 7 |
<span style="font-size: 18pt; font-family: 'times new roman', times, serif;">//Resets the sequence if it is invalid or timeouts if(sequence.length() > 2 || sequence.equals("11") || sequence.equals("22") || timeoutCounter > 200){ sequence=""; }</span> |
If the sequence is one if the length of the sequence is only one and then the timeout counter is incremented else it’s it becomes zero so this condition helps us because when it becomes 200 then only the sequence becomes invalid.
1 2 3 4 5 6 7 8 9 |
<span style="font-size: 18pt; font-family: 'times new roman', times, serif;"> if(sequence.length() == 1){ // timeoutCounter++; }else{ timeoutCounter=0; }</span> |
So those are the conditions for processing the data for the triggers of the ultrasounds. So we have done the part where the numbers of people are calculated and now we have to check whether the number of people is greater than the maximum allowed. So that is what we will do now if the number of people is high then we trigger the buzzer and that’s how people will know that the limit has been crossed. So if current people is greater than max people then tone buzzer and else no tone.
1 2 3 4 5 6 7 8 9 10 11 |
<span style="font-size: 18pt; font-family: 'times new roman', times, serif;">if(currentPeople > maxPeople){ tone(buzzerPin, 1, 500); displayText(String(currentPeople)); }else{ noTone(buzzerPin); }</span> |
So the tone and no tone are functions for the buzzer itself we pass in the buzzer pin number and the frequency of the sound is 1 and this is the duration of the sound 500. So if the numbers of people have been exceeded then the buzzer will sound.
Now we will trigger the display as well because we need to know how many people are there currently there so for that we are using an OLED display and we need three libraries so we include them we have discuss it in detail in previous articles.
1 2 3 4 5 |
<span style="font-size: 18pt; font-family: 'times new roman', times, serif;">#include <Adafruit_SSD1306.h> #include <Wire.h> #include <Adafruit_GFX.h></span> |
So before doing it we need to include the libraries. So after installing the libraries we will define the size of the screen:
1 2 3 |
<span style="font-size: 18pt; font-family: 'times new roman', times, serif;">#define SCREEN_WIDTH 128 #define SCREEN_HEIGHT 64</span> |
It is a small screen it has 128 width and 64 height so after that we need to initialize the screen
1 |
<span style="font-size: 18pt; font-family: 'times new roman', times, serif;">Adafruit_SSD1306 display(SCREEN_WIDTH,SCREEN_HEIGHT, &Wire, -1);</span> |
The address is usually known already by the display and -1 is another argument, after that we define a function to display the text onto the display so, void display text we pass in a string and here we have a couple of lines so first you have to clear the display because if you don’t do that it will just display what has what has already been there from before, then set the text size to three and set the text color to white, set the cursor to zero, and these are just default functions then display the text that is passed in and then display.display will finally display the text.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
<span style="font-size: 18pt; font-family: 'times new roman', times, serif;">void displayText(String txt){ display.clearDisplay(); display.setTextSize(3); display.setTextColor(WHITE); display.setCursor(0,0); display.print(txt); display.display(); }</span> |
in the setup we begin the display
1 |
<span style="font-size: 18pt; font-family: 'times new roman', times, serif;">display.begin(SSD1306_SWITCHCAPVCC, 0x3C);</span> |
Then we call the display text function which we defined and we pass in a string.
1 |
<span style="font-size: 18pt; font-family: 'times new roman', times, serif;">displayText("Visitor Counter");</span> |
So the setup function will be called first and it is called only once so the visitors counter text will be displayed once and then in the loop function we will display the number of people in the shop. We display the current people and we have to write the command
1 |
<span style="font-size: 18pt; font-family: 'times new roman', times, serif;">displayText(String(currentPeople));</span> |
When the number of people has exceeded five and the buzzer will start buzzing. When the person will leave, the counter has been decremented and the buzzer will be stopped ringing.
Super.
I need this for my wedding reception. I just want to add one line.
1: currently
2: today in total
I need a full project materials on this specific topic!