Attendance and Temperature Recorder with Sanitizer Dispenser
679 2
joel joseph

Attendance and Temperature Recorder with Sanitizer Dispenser

What I have made here is an attendence register which records the temperature of a registered user...

Description:-

What I have made here is an attendence register which records the temperature of a registered user and dispenses sanitizer. This was an idea that came up to me while I had to attend offline classes. Every single day a staff member would sit in front of the entrance and would take note of the student's name, their phone number and temperature. So this got me thinking "why cant we just automate this?", I mean, that's the entire essence of automation right? to perform repeated tasks without any human intervention. Moreover this project abides with the current social distancing policies enforced by our government. The machine identifies a registered user via face recognition, measures temperature and then dispenses sanitizer. Another add-on feature is that the collected temperature data (along with the corresponding name and phone number) would be sent as an excel file via gmail to the intended receiver. This project can be used in offices or any educational institution as these are the places where attendence is mainly recorded.

Project Used Hardware

HC-SR04 Ultrasonic Sensor Module (x3), Arduino UNO R3 Development Micro controller Board, Raspberry Pi 4 8GB with 5MP Camera Board Module, Mlx90614 Contactless Ir Infrared Temperature Sensor Module, MG995 TowerPro Servo Motor, 20x4 Line LCD Display, I2C SP Serial Interface Module Port For LCD display, 5v Active buzzer

Project Used Software

Arduino IDE, Geany, face_recognition(https:/ /github.com/ageitgey/face_recognition), i2cLcd python module(https:/ /github.com/the-raspberry-pi-guy/lcd)

Face Recognition System

Attendance System

Temperature Monitoring System

Project Hardware Software Selection

For the hardware , I have included three HC-SR04 Ultrasonic sensors which act as triggers for the raspberry pi camera , the MLX90614 IR temperature sensor and the M6995 servo motor . The MLX90614 IR temperature sensor reads the temperature of the user and the servo motor helps in dispensing sanitizer. A 20x4 LCD display has been used with an i2c serial interface module. The reason for including the i2c module was to save pin space as the LCD alone uses 16 pins whereas with the i2c module, we just need 4. At its core I have used both an Arduino UNO and a Raspberry Pi 4. The RPI4 is has more computing power than the Arduino but the Arduino is more capable of handling sensor related functions. So that’s why I decided to take the best from both worlds and bridged them via serial ports. The 5v active buzzer is connected to the raspberry pi for high temperature alerts For the Software part , Arduino IDE was used for admin/uploading code to the arduino. For writing python code I made use of the Geany IDE. The face_recognition python module (https:/ /github.com/ageitgey/face_recognition) was used for face recognition and the i2cLcd python module(https://github.com/the-raspberry-pi-guy/lcd) was used to control the lcd.

Circuit Diagram

Attendance System Circuit Diagram

Code

Soul.py

import face_recognition

import os

import pickle

import serial

import ast

import numpy as np

import drivers

import time

import RPi.GPIO as gpio

 

 

gpio.setmode(gpio.BOARD)

 

buzzerpin = 40

 

 

gpio.setup(buzzerpin,gpio.OUT)

 

 

display = drivers.Lcd()

 

devices = ['/dev/ttyACM0','/dev/ttyACM1']

 

 

for device in devices:

 

 try:

  ser = serial.Serial(device, 9600 , timeout=1)

  ser.flush()

  break;

 

 except Exception as e :

     continue;

    

      

 

def collect_send_data(send_string) :

    print(send_string)

    ser.write(send_string.encode('utf-8'))

   

def find_ip():

    ip=os.popen('hostname -I').read()

    ip = ip.replace("\n","")

    if ip=="" :

     ip = ' NO INTERNET' 

    return ip

 

face_image = []

face_encodings = {}

phone_numbers = {}

attendees = []

 

 

with open('/home/pi/faceR_prj/encodings.dat','rb') as f:

    face_encodings = pickle.load(f)

 

 

 

known_faces = np.array(list(face_encodings.values()))     

 

 

 

known_face_names = list(face_encodings.keys())

 

 

 

time.sleep(5)

 

while(1):

 display.lcd_clear()

 display.lcd_display_string("SYSTEM ACTIVE", 1)

 display.lcd_display_string("YOUR IP:"+find_ip(),3)

 collect_send_data(',')

   

 while(1):

    if find_ip()==' NO INTERNET' :

      find_ip()

    message_recieved = ser.readline().decode('utf-8')

    if '1' in message_recieved:

        print(message_recieved)

        break

    if 's' in message_recieved:

        print(message_recieved)

        continue   

 display.lcd_clear()

 display.lcd_display_string("     SAY CHEESE!!", 2)

 os.system('raspistill -w 640 -h 480 -t 2000 -o /home/pi/faceR_prj/pic.jpg')

 unknown_image = face_recognition.load_image_file("/home/pi/faceR_prj/pic.jpg")

 display.lcd_clear()

 os.system('sudo rm -r /home/pi/faceR_prj/pic.jpg')

 

 try:

    unknown_face_encoding = face_recognition.face_encodings(unknown_image)[0]

   

 

 except IndexError:

    print("NO FACE DETECTED")

    display.lcd_clear()

    display.lcd_display_string("NO FACE DETECTED", 1)

    display.lcd_display_string("PLEASE TRY AGAIN", 2)

    collect_send_data(',')

    time.sleep(3)

    display.lcd_clear()

    continue

 

 

 

 matches = face_recognition.compare_faces(known_faces,unknown_face_encoding,0.46)

 print(matches)

 name = "Unknown"

 

 face_distances = face_recognition.face_distance(known_faces,unknown_face_encoding)

 best_match_index = np.argmin(face_distances)

 if matches[best_match_index]:

                name = known_face_names[best_match_index]           

           

 if name == "Unknown":

   display.lcd_clear()

   display.lcd_display_string("   UNREGISTED USER", 1)

   display.lcd_display_string("   PLEASE CONTACT " ,2)

   display.lcd_display_string("  YOUR LOCAL ADMIN", 3)

   collect_send_data(',')

   time.sleep(3)

 

 elif name in attendees:

     display.lcd_clear()

     display.lcd_display_string("   USER DATA  ", 1)

     display.lcd_display_string("  WAS PREVIOUSLY  " ,2)

     display.lcd_display_string("    LOGGED  " ,3)

     collect_send_data(',')

     time.sleep(3)

       

      

 else:  

   attendees.append(name)  

   display.lcd_clear()

   display.lcd_display_string("WELCOME :", 1)

   display.lcd_display_string(name.upper(), 2)

   time.sleep(2)

   display.lcd_clear()

   display.lcd_display_string("BRING YOUR ARM TO ", 1)

   display.lcd_display_string("MEASURE TEMPERATURE", 2)

   time.sleep(2)

   collect_send_data('*')

   flag=0

   for num in range(0,6):

     message_recieved = ser.readline().decode('utf-8')

     if message_recieved:

       flag=1 

       display.lcd_clear()

       LEN = len(message_recieved)

       message_recieved = message_recieved.replace(message_recieved[LEN-1],"")

       message_recieved = message_recieved.replace(message_recieved[LEN-2],"")       

       temperature = ast.literal_eval(message_recieved)

       attendees.append(name)

       NewName = name

       NewName = NewName.replace(" ","_")

       os.system('python3 /home/pi/faceR_prj/attendence.py '+NewName+' '+message_recieved)

       display.lcd_display_string("TEMPERATURE : "+message_recieved, 1)

       time.sleep(2)

 

       if temperature < 36 :

            sanflag=0

            display.lcd_clear()

            display.lcd_display_string("PLEASE SANITIZE", 1)

            display.lcd_display_string("BEFORE YOU LEAVE", 2)

            time.sleep(2)

            collect_send_data('#')

            for num in range(0,6):

              message_recieved = ser.readline().decode('utf-8')

            

              if message_recieved :

                 sanflag = 1

                 display.lcd_clear()

                 display.lcd_display_string("   HAVE A NICE",2)

                 display.lcd_display_string("       DAY",3)

                 time.sleep(2)

                 break

              else:   

                 numstr =str(num)

                 display.lcd_display_string("["+numstr+"/5s TILL TIME OUT]", 3)

                 time.sleep(1)

                

            if sanflag == 0:

                display.lcd_clear()

                display.lcd_display_string(" TIME OUT ",2)

                time.sleep(2)      

 

       else:

         display.lcd_clear()

         display.lcd_display_string("****WARNING****",1)

         display.lcd_display_string("TEMPERATURE VALUE",2)

         display.lcd_display_string("  EXCEEDS NORMS",3)

         display.lcd_display_string("  ACCESS DENIED",4)

         gpio.output(buzzerpin,gpio.HIGH)  

         collect_send_data('a')   

         time.sleep(5)

         gpio.output(buzzerpin,gpio.LOW)

         time.sleep(1)

        

      

       break

     else :

       numstr =str(num) 

       display.lcd_display_string("["+numstr+"/5s TILL TIME OUT]", 3)

       time.sleep(1)   

      

  

   if flag == 0:   

        display.lcd_clear()

        display.lcd_display_string("   TIME OUT", 2)

        time.sleep(2)

        collect_send_data('a')

        time.sleep(2)

       

       

 print(name)

Mailer.py

 

 

import email, smtplib, ssl

from datetime import date ,datetime

import pickle

import os

from email import encoders

from email.mime.base import MIMEBase

from email.mime.multipart import MIMEMultipart

from email.mime.text import MIMEText

import openpyxl

from openpyxl import load_workbook

from openpyxl.styles import Font

wb = openpyxl.Workbook()

TriggerTime = "12:14:00"

def Trigger():

    current_time = str(datetime.now().strftime("%H:%M:%S"))

    #print(current_time)

    if TriggerTime == current_time:

        return 1

    return 0

while(1):

 if Trigger() == 0 :

     continue      

 subject = "Today's attendence"

 body = "Data collected from covisafe"

 sender_email = ""    

 receiver_email = ""

 password = ""

 message = MIMEMultipart()

 message["From"] = sender_email

 message["To"] = receiver_email

 message["Subject"] = subject

 message["Bcc"] = receiver_email

 message.attach(MIMEText(body, "plain")

 sheet = wb.active

 temperatures={}

 phone_numbers={}

 try:

     with open('/home/pi/faceR_prj/temperature.dat','rb') as f:

         temperatures=pickle.load(f)

     with open('/home/pi/faceR_prj/phonenos.dat','rb') as P:

         phone_numbers=pickle.load(P)

     names = list(temperatures.keys())        

     FONT = Font(bold=True)

     sheet.cell(row=1, column=1).value="Name"

     sheet.cell(row=1, column=2).value="Phone Number"

     sheet.cell(row=1, column=3).value="Temperature"

     sheet['A1'].font = FONT

     sheet['B1'].font = FONT

     sheet['C1'].font = FONT

     i=2

     for name in names:

        sheet.cell(row=i, column=1).value=name

        sheet.cell(row=i, column=2).value=phone_numbers[name]

        sheet.cell(row=i, column=3).value=temperatures[name]

        i=i+1

     sheet.column_dimensions['A'].width = 20

     sheet.column_dimensions['B'].width = 20

     sheet.column_dimensions['C'].width = 20

 except :

      FONT = Font(bold=True)

      sheet.cell(row=1, column=1).value="N/A"

      sheet.cell(row=1, column=2).value="N/A"

      sheet.cell(row=1, column=3).value="N/A"

      sheet['A1'].font = FONT

      sheet['B1'].font = FONT

      sheet['C1'].font = FONT

 Date = str(date.today())

 wb.save("/home/pi/faceR_prj/Register/"+Date+".xlsx")

 filename = Date+".xlsx" 

 with open("/home/pi/faceR_prj/Register/"+filename, "rb") as attachment:

    part = MIMEBase("application", "octet-stream")

    part.set_payload(attachment.read())

 encoders.encode_base64(part)

 part.add_header(

    "Content-Disposition",

    f"attachment; filename= {filename}",

 )

 message.attach(part)

 text = message.as_string()

 context = ssl.create_default_context()

 try:

     with smtplib.SMTP_SSL("smtp.gmail.com", 465, context=context) as server:

         server.login(sender_email, password)

         server.sendmail(sender_email, receiver_email, text)

         os.system("echo "" > /home/pi/faceR_prj/temperature.dat")

 except:

     print("No internet access. Unable to send mail")

Attendance.py

import sys

import pickle

arg1 = sys.argv[1].replace("_"," ")

arg2 = sys.argv[2]

attendee = {}

try:

            with open('/home/pi/faceR_prj/temperature.dat','rb') as f:

                        attendee=pickle.load(f)

                        attendee[arg1]=arg2                       

except:

            attendee[arg1] = arg2         

print(attendee)         

with open('/home/pi/faceR_prj/temperature.dat','wb') as p:

    pickle.dump(attendee,p) 

Adduser.py

import pickle

import os

import face_recognition

face_encoding = {}

Name = input("Name: ")

Phoneno = input("Phone number :")

NewName = Name

NewName = NewName.replace(" ","_")

os.system('raspistill -w 640 -h 480 -o /home/pi/faceR_prj/oldfiles/'+NewName+'.jpg')

try:

 with open('/home/pi/faceR_prj/encodings.dat','rb') as F:

    face_encoding = pickle.load(F)

except EOFError:

    face_encoding = {}   

try:

 with open('/home/pi/faceR_prj/phonenos.dat','rb') as P:

    Phonenos = pickle.load(P)   

except EOFError:

    Phonenos = {}  

try:

    face_encoding[Name] = face_recognition.face_encodings(face_recognition.load_image_file('/home/pi/faceR_prj/oldfiles/'+NewName+'.jpg'))[0]

    Phonenos[Name] = Phoneno

except IndexError:

    print("NO FACE DETECTED...")

    quit()

with open('/home/pi/faceR_prj/encodings.dat','wb') as f:

    pickle.dump(face_encoding,f)

with open('/home/pi/faceR_prj/phonenos.dat','wb') as p:

    pickle.dump(Phonenos,p)   

os.system('sudo rm -r /home/pi/faceR_prj/oldfiles/'+NewName+'.jpg')

print("User added to database")

Arduino Code

#include <Wire.h>

#include <LiquidCrystal_I2C.h>

#include <Adafruit_MLX90614.h>

#include <Servo.h>

int trigpin1=12;

int echopin1=11;

int trigpin2=7;

int echopin2=6;

int trigpin3=8;

int echopin3=9;

int servopin = 3;

int pingtraveltime;

int pingvalue;

int Length;

Adafruit_MLX90614 mlx = Adafruit_MLX90614();

LiquidCrystal_I2C lcd(0x3F,20,4);

Servo servo ;

int ultrasonic(int trigpin,int echopin)

{

   digitalWrite(trigpin,LOW);

  delayMicroseconds(10);

  digitalWrite(trigpin,HIGH);

  delayMicroseconds(10);

  digitalWrite(trigpin,LOW);

  delayMicroseconds(10);

  pingtraveltime=pulseIn(echopin,HIGH);

  delay(25);

  delay(1000);

  return pingtraveltime;

}

void setup() {

  // put your setup code here, to run once:

 pinMode(trigpin1,OUTPUT);

 pinMode(echopin1,INPUT);

 pinMode(trigpin2,OUTPUT);

 pinMode(echopin2,INPUT);

 pinMode(trigpin3,OUTPUT);

 pinMode(echopin3,INPUT);

 Serial.begin(9600);

 mlx.begin(); 

 servo.attach(servopin);

 servo.write(0);

 lcd.init();

 lcd.backlight();

 lcd.init();

 lcd.setCursor(1,1);

 lcd.print("Booting");

}

void loop() {

  String incoming_data;

 while(Serial.available() == 0 )

     {}     

      incoming_data =  Serial.readStringUntil("\n");

  Length = incoming_data.length()   ;

 if(incoming_data[Length-1] == ',')

 {

  while(1)

  {

    pingvalue = ultrasonic(trigpin1,echopin1) ;

   if(pingvalue > 100 && pingvalue < 5000)

    {

     Serial.println('1');

     break;

    }

   else

    {

     Serial.println('s');

    }

  }

 }

  while(Serial.available() == 0 )

     {}     

      incoming_data =  Serial.readStringUntil("\n");

  Length = incoming_data.length();

  int count = 0;

  if(incoming_data[Length-1]=='*')

    {

   while(count<7)

   { 

       pingvalue = ultrasonic(trigpin2,echopin2);

        if(pingvalue > 100 && pingvalue < 2000)

         {

           double temperature_in_c = mlx.readObjectTempC();

           delay(500);

           String value = String(temperature_in_c);

           Serial.println(value);

           delay(2000);

           break; 

         }

         else

          delay(1000);

         count++;

    }

  count =0;

  while(Serial.available() == 0 )

     {}     

      incoming_data =  Serial.readStringUntil("\n");

  Length = incoming_data.length();

  if(incoming_data[Length-1]=='#')

  {

   while(count<7)

   { 

       pingvalue = ultrasonic(trigpin3,echopin3);

        if(pingvalue > 100 && pingvalue < 2000)

         {

           servo.write(0);

           delay(1000);

           servo.write(140);

           delay(1000);

           servo.write(0);

           delay(1000);

           Serial.println("STOP");

           break; 

         }

        else

          delay(1000);

         count++;

    } 

  }

 }

}