Introduction: WiFi Person Counter

About: I am a student who enjoys building and soldering circuits with Arduinos and ICs, like the 555 timer. I also do a bit of coding in VB.NET, JS, HTML, Python, C++, C, Batch Script.

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

Step 1: 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!

Step 2: 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.

Step 3: 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.

Step 4: 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. :)

Step 5: 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>&nbsp;&nbsp;&nbsp;<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>&nbsp;&nbsp;&nbsp;<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.90but 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!

Step 6: How to Set It Up and Use It

Nice job! You finished! In order to use it, you can follow these steps:


  1. 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.
  2. Wait a few seconds for the led to turn off and connect to WiFi to start the server.
  3. Open a browser (like Google) and head to the IP address that the Serial Monitor spit out. (Mine was http://10.0.0.90)
  4. 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.
  5. Check out the ESP's status on the website!
  6. 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

Step 7: 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!!!

Microcontroller Contest

Participated in the
Microcontroller Contest