Friday, May 7, 2021

Person Counter part 2

For an index to all of my stories click this text

Last week I showed you my customer counter. I made it for the company where I work that has a webshop and a physical shop. Due to the pandemic we are only allowed 50 people max at the same time in our shop. So I designed a counter that manually keeps track of the number of people that are in the shop. You can re-read that story here http://lucstechblog.blogspot.com/2021/05/person-counter.html

The customer counter has a fixed number of 50 persons as maximum. And I wrote that I used an ESP8266 for this project as it has the ability to build a webpage that allows to set the maximum at a different number. That got me quite a lot of emails from people asking to publish the software for that.

Well I'll do better then that. This story gives you the software and I also designed a casing that can be 3D printed. You can find the design and STL files also in this story.

The Person Counter with webpage.

Here is the complete program.

// ======================================================
//            Customer counter program
// Webserver makes it possible to set the maximum
// number of customers
// Wemos D1 has 3 buttons attached to count customers
// intended for shop use during corona pandemic 
// when shops are allowed a maximum amount of customers
// By Luc Volders
// http://lucstechblog.blogspot.com/
// ======================================================

#include <TM1637Display.h>

#include <ESP8266WiFi.h>
#include <ESP8266WebServer.h>

#include <EEPROM.h>
#define EEPROM_SIZE 100

ESP8266WebServer server(80);

// Your routers credentials
const char* ssid = "YOUR-ROUTERS-NAME";
const char* password = "PASSWORD";


String textosend_string;


const int CLK = D6; //Set the CLK pin connection to the display
const int DIO = D5; //Set the DIO pin connection to the display

const int upbut = D1;
const int downbut  = D2;
const int totbut = D7;
 
int maxnum=0; 
int person = 0;
int total = 0;
 
TM1637Display display(CLK, DIO); //set up the 4-Digit Display.

// =========================================
// Here is the HTML page
// =========================================
String getPage()
  {
  String page = "<!DOCTYPE HTML>";
  page += "<html>";
  page += "<head>";
  page += "<meta name = \"viewport\" content = \"width = device-width, initial-scale = 1.0 maximum-scale = 2.5, user-scalable=1\">";
  page += "<title>Luc's Person Counter</title>";
  page += "<body style='background-color:powderblue;'>";
  page += "</head>";
  page += "<body>";
  page += "<h1 style='color:red'>Parameters for person counter</h1>";

  //Form to put the data in
  page += "<FORM action=\"/\" method=\"post\">";
  page += "Give the maximum amount of allowed customers<br>";
  page += "Number is now set at : ";
  page += maxnum;
  page += "<br><br>";
  page += "<input type=\"text\" name=\"textosend\" id=\"textosend\" value=\"Max number persons\">";
  page += "<br><br>";
  page += "<input type=\"submit\" value=\"Send to Person Counter\">";
  page += "</form>";
  page += "<br>";
  page += "<br>";
  page += "</script>";  
  page += "</body>";
  page += "</html>";
  return page;
  }


// ==================================================
// Handle for page not found
// ==================================================
void handleNotFound()
{
  server.send(200, "text/html", getPage());
}


// ==================================================
// Handle submit form
// ==================================================
void handleSubmit()
{
  //Text to show
  if (server.hasArg("textosend"))
      {
      textosend_string = server.arg("textosend");
      Serial.print("The received text is:             ");
      Serial.println(textosend_string);
      maxnum = textosend_string.toInt();
      EEPROM.write(0, maxnum); //the value to write in eeprom
      EEPROM.commit();
      }

  server.send(200, "text/html", getPage());       //Response to the HTTP request
}  


// ===================================================
// Handle root
// ===================================================
void handleRoot() 
{   
  if (server.args() ) 
    {
    handleSubmit();
    } 
  else 
    {
    server.send(200, "text/html", getPage());  
    }
}


// ===================================================
// Setup
// ===================================================
void setup()
{
  delay(1000);
  EEPROM.begin(EEPROM_SIZE);
  maxnum = EEPROM.read(0);
  if (maxnum == 0)
  {
     maxnum = 50;   
  }
  Serial.begin(115200);

  display.setBrightness(0x0a); //set the diplay to maximum brightness

  pinMode(D1, INPUT_PULLUP);
  pinMode(D2, INPUT_PULLUP);
  pinMode(D7, INPUT_PULLUP);

  // Connect to Wi-Fi network with SSID and password
  Serial.print("Connecting to ");
  Serial.println(ssid);
  WiFi.begin(ssid,password);
  
  for (int i=1; i<30; i++)
  {
  //while (WiFi.status() != WL_CONNECTED) 
  if (WiFi.status() != WL_CONNECTED)
  {
    delay(500);
    Serial.print(".");
  }
  }


  if (WiFi.status() != WL_CONNECTED)
  {
  Serial.print("Setting soft-AP ... ");
  boolean result = WiFi.softAP("ESPsoftAP_01", "perscount");
  if(result == true)
  {
    Serial.println("Ready");
  }
  else
  {
    Serial.println("Failed!");
  }
  }
  
  // Print local IP address and start web server
  Serial.println("");
  Serial.println("WiFi connected.");
  Serial.println("IP address: ");
  Serial.println(WiFi.localIP());
  server.begin();
  server.on("/", handleRoot);
  server.onNotFound(handleNotFound);

  server.begin();
  delay(500);
}


// ===================================================
// Loop
// ===================================================
void loop()
{  
  server.handleClient(); 
  if (digitalRead(upbut) == 0)
 {
   person = person +1;
   total = total +1;
  if (person >maxnum)
     {
       display.showNumberDec(8888);
     }
   delay(500);
 }
 if (digitalRead(downbut) == 0)
 {
   person = person -1;
   if (person <0)
   {
     person = 0;
   }
    delay(500);
 }
 if (digitalRead(totbut) == 0)
 {
   display.showNumberDec(total);
   delay(3000);
 }
 display.showNumberDec(person);
}


Normally in all the stories in this weblog I give you an explanation on how the software works. But as there are a lot of tricks in it that are going to be discussed in future stories I will not get into the details here.

There are however two lines that you need to alter.

const char* ssid = "YOUR-ROUTERS-NAME";
const char* password = "PASSWORD";


In these lines fill in your own (or the shop's) routers name and password so the ESP8266 can connect to your network.

As stated I am not going into the details how the software works But I will show you how to use it.

How to use the Person Counter

First let me say that if you are going to use this on a fixed adress with a fixed maximum of people allowed at the same time you can just use the version discussed in the previous article.

At first start you do not need to access the webserver. The maximum number of persons is standard set at 50. The counter starts at 0. Pressing the green button adds a person. Pressing the red button subtracts a person and pressing the grey button shows the total amount of persons that visited the shop that day.

Removing the power resets the counter to 0.

If you need to alter the maximum number of people allowed in your shop you need to access the webserver.

As shown above you can set the credentials of your router in the software and if you do the person counter automatically connects to that router.
You can connect with your computer, phone or tablet to the person counter's IP adress. If you do not know the IP adress you can check your router to see what it is. In a arger company you could ask the IT manager. Another option is to connect the person counter with a USB cable to your Android phone and use an USB terminal program like USB Terminal Universal to be found in the Android Play Store.

If you do not set the credentials or move the person counter to a different location with different router credentials the person counter starts an access point.
In that case look in the wifi settings on your phone and connect to the ESP.
The Person Counter will be named Person Counter and the password is perscount.
The phone will tell you that the connection is made but that there is no internet available. That is OK.

Now point your browser to 192.168.4.1 this is the standard IP number for the ESP8266.

And there is the webpage.



The counter is when no alterations have been made set to 0. The program reads that number from its permanent storage and interprets that as being 50. I set this as the default value because this program was initially just meant for my work environment.



Now you can alter the text "Max number persons" in the number you want. Make sure you remove all of the text. Here I replaced it with 20 and then pressed the "Send to Person Counter" button. The webpage updates immediately and the number is stored in the permanent memory of the Wemos D1.

Next time you reboot the Wemos it automatically fetches the stored number (which now will be 20) and uses that in the program. So if the number exceeds 20 an alarm will be shown on the display being 8888.

For those that want to examine the program closer there are a few neat things in it.
- The webserver sends a form with a textfield with the post command
- There is permanent storage reserved in the Wemos memory with the EEPROM library
- Wifi tries to establish a connection to a known router and if that fails starts an accesspoint.
- The main program works wether you use the webserver or not.

Dont't worry. All these features will be discussed in later tutorials on this weblog.

Casing

In the previous story I showed the hardware schematic and showed that I put it on a stripboard for permanent use.

Off course I can not put a few stripboards on a persons desk and say: here you go, here is the person counter. It had to have a casing.



So I designed a casing in Tinkercad. 


To download them you need to create an account with Tinkercad. Don't hesitate, it's free !!



It took my Creality CR20 no less then 7 hours to print the casing !!!
Make sure you have enough filament on the spool. In your slicer set support everywhere. I used Prusa slicer for this as both the Creality slicer and Repetier did some weird things with the walls of the casing.

The small help parts are there to mount the stripboard in the casing and used as spacers. You could use some small strips of cardboard for that. Printing them took me just 7 minutes, so no big deal.



I started with re-enforcing the corners by adding some hot glue everywhere.



Next I glued the small boxes in the corners where the buttons are to come.



The stripboard with the buttons glued in place.



The small rectangular box was glued next to the display. It works as a spacer.



Then the display was glued into the casing.



And there we are.
As I was short of time I did not had the time to print a bottom and just glued a piece of cardboard at the bottom. I glued the USB cable to the cardboard and that's it. I was short of time because I needed it next day at my work.

As the dimensions are known when you download the model from Tinkercad you can easily print a bottom and back plate yourself.

Next day I took it to my work and it works as a charm !!!

Not only was this a fun project but it is also something real practical.

Till next time
have fun !!

Luc Volders