WiFi Person Counter
by skywiredvt in Circuits > Microcontrollers
2270 Views, 20 Favorites, 0 Comments
WiFi Person Counter
Tracking the amount of people that walk by a specific point is a tricky task, but this simple device reduces the difficulty level significantly. Using the ESP8266, we can make a useful device that can track thousands of people per day, and can be connected to remotely in order to control and monitor the device. I was always curious to see how many people come and go through the hallway in our home, because it seemed like a lot. After building this, I was able to find out the answer to my question!
You can find this project on Arduino.cc with source code as well: https://create.arduino.cc/projecthub/transistor_man/esp8266-nodemcu-wifi-person-counter-fd0dd6
Find the pastebin code here: https://pastebin.com/vVzCVdET
Supplies
For this project, I used:
1x Ender 3D printer.
1x ESP8266 WeMos
6x Wires
1x HC-SR04 Ultrasonic Distance Sensor
1x Tripod Stand
1x LED with 220 ohm resistor
1x Micro USB cable
3D Print the Box
The first thing I did, was design a box for the entire project to fit into. This model is a pretty large box that can easily fit everything required to run the project. Originally, I designed it to fit 1 or 2 18650 Li-on rechargeable batteries, but I made the project simpler by just using a micro USB adaptor. If you want, you may still be able to fit the batteries.
NOTE: The box does NOT have any holes in it for the sensor or ESP. You will need to drill them (or in my case, dremel them) out so the HC-SR04 sensor and micro USB cable will fit.
You can export the .skp file to .stl. For some reason, I was unable to upload the .stl file to this instructable. Sorry!
Downloads
Solder the Electronics Together
Now, we get to solder everything together! I will attach a wiring diagram to follow along with.
Also, if you connect the sensor or LED to different pins, make sure that the pins on the ESP8266 correspond to the pins in the code, as they are different numbers.
Make Some Holes for the Sensor in the Box
Now, this is where you could modify the .skp file so that you could just print the box with holes in it, or you could just do what I did, and drill the holes out so the sensor fits. I also made a small hole on the bottom of the box, so I could attach a tripod to it and have it stand wherever.
Turns out a 1/2" drill bit is not big enough for the sensor's cylinders to fit through. Maybe try a 1 inch bit, if you have one.
Put the Components in the Box
Now, we can just put everything inside! This part is pretty easy. Just glue the components into the box and make sure no wires are crossed. Then, everything should be fine. The inside of my box looks pretty messy, but that's OK, nobody needs to see the inside except you. :)
The Code
Now. The assembly is complete. There is no more wiring involved. Nothing... except the CODE! Nah, the code part is pretty easy. I'll provide the code below so that it is simple as just copy-pasting the code into the Arduino IDE.
Here is the code that I modified that was originally made for an ESP web server: Note: The code may change from time to time, as I may be updating it.
Last updated: 8/30/2022
/********* Original Code By: Rui Santos Modified By: skywired *********/ #include <ESP8266WiFi.h> int personsCounted = 0; // Replace with your network credentials const char* ssid = "Pickle Barrel"; const char* password = "m0987654321H"; int x = 0; // Set web server port number to 80 WiFiServer server(80); String header; bool led = false; const int trigPin = 4; const int echoPin = 5; long duration; int distance; int calDistance = 0;//Don't change // Current time unsigned long currentTime = millis(); // Previous time unsigned long previousTime = 0; // Define timeout time in milliseconds (example: 2000ms = 2s) const long timeoutTime = 2000; void setup() { pinMode(12, OUTPUT);//Declaring GPIO 12 as an output (connects to LED) analogWrite(12, 3);//Write LED to 3 with PWM Serial.begin(9600); // Starts the serial communication //****************************************************** //This code is used to start the web server //****************************************************** // Connect to Wi-Fi network with SSID and password Serial.print("Connecting to "); Serial.println(ssid); WiFi.begin(ssid, password); while (WiFi.status() != WL_CONNECTED) { delay(500);//Wait .5 seconds before trying again to connect. This may take a few tries Serial.print("."); } // Print local IP address and start web server Serial.println(""); Serial.println("WiFi connected."); Serial.println("IP address: "); Serial.println(WiFi.localIP());//REMEMBER THIS IP ADDRESS! YOU WILL NEED TO USE IT TO CONNECT TO IT! server.begin();//Start the server analogWrite(12, 0);//Turn the LED off pinMode(trigPin, OUTPUT); // Sets the trigPin as an Output pinMode(echoPin, INPUT); // Sets the echoPin as an Input } void loop() { //****************************************************** // This code is for calculating distance on the HC-SR04 //****************************************************** // Clears the trigPin digitalWrite(trigPin, LOW); delayMicroseconds(2); // Sets the trigPin on HIGH state for 10 micro seconds digitalWrite(trigPin, HIGH); delayMicroseconds(10); digitalWrite(trigPin, LOW); // Reads the echoPin, returns the sound wave travel time in microseconds duration = pulseIn(echoPin, HIGH); // Calculating the distance distance = duration * 0.034 / 2; //****************************************************** //This code detects if a user has connected to the ESP //****************************************************** WiFiClient client = server.available(); // Listen for incoming clients if (client) { // If a new client connects, Serial.println("New Client."); // print a message out in the serial port String currentLine = ""; // make a String to hold incoming data from the client currentTime = millis(); previousTime = currentTime; while (client.connected() && currentTime - previousTime <= timeoutTime) { // loop while the client's connected currentTime = millis(); if (client.available()) { // if there's bytes to read from the client, char c = client.read(); // read a byte, then Serial.write(c); // print it out the serial monitor header += c; if (c == '\n') { // if the byte is a newline character // if the current line is blank, you got two newline characters in a row. // that's the end of the client HTTP request, so send a response: if (currentLine.length() == 0) { // HTTP headers always start with a response code (e.g. HTTP/1.1 200 OK) // and a content-type so the client knows what's coming, then a blank line: client.println("HTTP/1.1 200 OK"); client.println("Content-type:text/html"); client.println("Connection: close"); client.println(); if (header.indexOf("GET /update") >= 0) { Serial.println("Update"); } else if (header.indexOf("GET /reset") >= 0) { Serial.println("Reset"); personsCounted = 0; } else if (header.indexOf("GET /calibrate") >= 0) { digitalWrite(12, HIGH); Serial.println("calibrating!"); digitalWrite(trigPin, LOW); delayMicroseconds(2); // Sets the trigPin on HIGH state for 10 micro seconds digitalWrite(trigPin, HIGH); delayMicroseconds(10); digitalWrite(trigPin, LOW); // Reads the echoPin, returns the sound wave travel time in microseconds duration = pulseIn(echoPin, HIGH); // Calculating the distance calDistance = duration * 0.034 / 2; calDistance = calDistance - 7; delay(1000); digitalWrite(12, LOW); } //****************************************************** //This code is for making the website the ESP is hoting. //****************************************************** //This is HTML code. You can modify it to your taste if you know what you are doing, but no modifications are required. client.println("<!DOCTYPE html><html>"); client.println("<head><meta name=\"viewport\" content=\"width=device-width, initial-scale=1\">"); client.println("<link rel=\"icon\" href=\"data:,\">"); client.println("<script>"); client.println("function cal() {"); client.println("alert('Calibrated!');"); client.println(""); client.println("}"); client.println("</script>"); // CSS to style the on/off buttons // Feel free to change the background-color and font-size attributes to fit your preferences client.println("<style>html { font-family: Helvetica; display: inline-block; margin: 0px auto;}"); client.println(".button { background-color: #195B6A; border: none; color: white; padding: 16px 40px;"); client.println("text-decoration: none; font-size: 30px; margin: 2px; cursor: pointer;}"); client.println(".button2 {background-color: #77878A;}</style></head>"); client.println("<body><br><center><u><h1>ESP8266 Person Counter Control Panel</h1></u>"); client.println("<br>"); client.println("<br>"); client.println("<h2>People Counted:</h2>"); client.println("<br>"); client.println("<h1>"); client.println(personsCounted); client.println("</h1>"); client.println("<br>"); client.println("<br>"); client.println("<br>"); client.println("<br>"); client.println("<p><a href=\"/reset\"><button class=\"button\">Reset Counter</button></a></p>"); client.println("<p><a href=\"/update\"><button class=\"button button2\">Update Counter</button></a></p>"); client.print("<p><a href=\"/calibrate\" id = \"calibrateButton\" onclick =\"cal()\"><button class=\"button button2\">Calibrate Sensor</button></a></p> <br><p>Sensor Threshold: "); client.print(calDistance); client.println("</p>"); client.println("<h3><a href=\"https://docs.google.com/presentation/d/1rl4b2HUcnA15HfbJAZuuupapFs2aXjrh8gPIO-D9RYU/present?slide=id.g14906e2b0e6_4_0\">Help and Instructions</a><h3>"); client.println("</center></body></html>"); client.println(); // Break out of the while loop break; } else { // if you got a newline, then clear currentLine currentLine = ""; } } else if (c != '\r') { // if you got anything else but a carriage return character, currentLine += c; // add it to the end of the currentLine } } } // Clear the header variable header = ""; // Close the connection client.stop(); Serial.println("Client disconnected."); Serial.println(""); } //****************************************************** //This code is for detecting people an flashing the LED //****************************************************** delay(1);//Wait 1 ms x++;//Increase the variable 'X' by one every 1 ms if (x == 350 || x == 351 || x == 352 || x == 353 || x == 354 || x == 355 && led == false) { digitalWrite(12, HIGH); //Turn LED on for a bit WITHOUT pausing the program using delays led = true;//sets the boolean to true } //Serial.println(calDistance); if (x > 350) { digitalWrite(12, LOW); x = 0;//Sets the light flash variable to 0 again //Turn LED off for a bit WITHOUT pausing the program using delays led = false;//sets the boolean to false } if (calDistance > 1180) { calDistance = 60; client.println("<!DOCTYPE html><html>"); client.println("<head><meta name=\"viewport\" content=\"width=device-width, initial-scale=1\">"); client.println("<link rel=\"icon\" href=\"data:,\">"); client.println("<script>"); client.println("function cal() {"); client.println("alert('calibrated!');"); client.println("}"); client.println("</script>"); // CSS to style the buttons // Feel free to change the background-color and font-size attributes to fit your preferences client.println("<style>html { font-family: Helvetica; display: inline-block; margin: 0px auto;}"); client.println(".button { background-color: #195B6A; border: none; color: white; padding: 16px 40px;"); client.println("text-decoration: none; font-size: 30px; margin: 2px; cursor: pointer;}"); client.println(".button2 {background-color: #77878A;}</style></head>"); client.println("<body><br><center><u><h1>ESP8266 Person Counter Control Panel</h1></u>"); client.println("<br>"); client.println("<br>"); client.println("<h2>People Counted:</h2>"); client.println("<br>"); client.println("<h1>"); client.println(personsCounted); client.println("</h1>"); client.println("<br>"); client.println("<br>"); client.println("<br>"); client.println("<br>"); client.println("<p><a href=\"/reset\"><button class=\"button\">Reset Counter</button></a></p>"); client.println("<p><a href=\"/update\"><button class=\"button button2\">Update Counter</button></a></p>"); client.print("<p><a href=\"/calibrate\" onclick =\"cal()\"><button class=\"button button2\">Calibrate Sensor</button></a></p> <br><p>Sensor Threshold: "); client.print("Distance is INVALID! (Over 1180cm / limit) Please adjust! [Reset sensor threshold to deault, 60cm]"); client.println("</p>"); client.println("<h3><a href=\"https://docs.google.com/presentation/d/1rl4b2HUcnA15HfbJAZuuupapFs2aXjrh8gPIO-D9RYU/present?slide=id.g14906e2b0e6_4_0\">Help and Instructions</a><h3>"); client.println("</center></body></html>"); client.println(); } if ( distance < calDistance && calDistance != 0) { personsCounted++;//Increase the amount of people counted by one digitalWrite(12, HIGH);//Turn on LED while (distance < calDistance && calDistance != 0) { delay(550);//Wait until person has passed. // Clears the trigPin digitalWrite(trigPin, LOW); delayMicroseconds(2); // Sets the trigPin on HIGH state for 10 micro seconds digitalWrite(trigPin, HIGH); delayMicroseconds(10); digitalWrite(trigPin, LOW); // Reads the echoPin, returns the sound wave travel time in microseconds duration = pulseIn(echoPin, HIGH); // Calculating the distance distance = duration * 0.034 / 2; } digitalWrite(12, LOW); } if (calDistance == 0) { for (int fadeValue = 0 ; fadeValue <= 150; fadeValue += 5) { // sets the value (range from 0 to 255): analogWrite(12, fadeValue); // wait for 30 milliseconds to see the dimming effect delay(30); } delay(500); // fade out from max to min in increments of 5 points: for (int fadeValue = 150 ; fadeValue >= 0; fadeValue -= 5) { // sets the value (range from 0 to 255): analogWrite(12, fadeValue); // wait for 30 milliseconds to see the dimming effect delay(30); } delay(500); } }
If you have any questions about the code, anything else, or if it doesn't work for any reason, PLEASE just ask a question in the comments, and I'll try to reply as soon as I can!
If there is an error in the code, please comment it down below, and I'll try and fix it ASAP!
You can find the code on pastebin as well: https://pastebin.com/vVzCVdET
IMPORTANT:
- You are going to need to change the SSID and PASSWORD field at the top of the code when uploading to the ESP8266. Just enter your WiFi name and password, and you should be all set!
- You will also need to open the Serial Monitor once you upload the code to the ESP. This should print out the IP address that you will need to connect to the ESP over WiFi. Mine was: http://10.0.0.90 but yours will be different, so keep an eye on the monitor for when it spits the address out.
- Once you have connected to the ESP8266, click the CALIBRATE button! Calibrating the sensor is very important, because if you don't the LED will just fade on and off waiting to be calibrated! Make sure to do so every time you power up the device. Note: It is recommended to only calibrate the sensor once! In order to re-calibrate it, you should unplug and re-plug the device to reset the previous value!
How to Set It Up and Use It
Nice job! You finished! In order to use it, you can follow these steps:
- Grab a micro USB cable, and plug it in to the device. You will see the LED come on dimly, showing that it is attempting to connect to WiFi.
- Wait a few seconds for the led to turn off and connect to WiFi to start the server.
- Open a browser (like Google) and head to the IP address that the Serial Monitor spit out. (Mine was http://10.0.0.90)
- IMPORTANT: Make sure you press the CALIBRATE button on the web page every time you power it up. If you don't the LED will just fade on and off waiting to be calibrated! Note: It is recommended to only calibrate the sensor once! In order to re-calibrate it, you should unplug and re-plug the device to reset the previous value.
- Check out the ESP's status on the website!
- Walk by the sensor and then update the website by either refreshing the page, or clicking the 'Update' button.
Extra help on setting up and using is available here: Instructions
Questions? Comments? Just post something in the comments down below, OR shoot me an e-mail at: skywiredvt@gmail.com
End
Thanks for reading this Instructable! If you make instructables too, you know that a lot of time and effort is put into writing them so that other people understand too. If you liked this, let me know!!!