Yash Nayak
Published © GPL3+

Smart Disinfection and Sanitation Tunnel

The smart tunnel prevents further outspread of COVID-19 / SARS-CoV-2. It can disinfect a person fully in a time span of just 15 seconds.

AdvancedFull instructions provided13 hours74,787

Things used in this project

Hardware components

Arduino UNO
Arduino UNO
×1
Jumper wires (generic)
Jumper wires (generic)
×1
PIR Motion Sensor (generic)
PIR Motion Sensor (generic)
×2
12V Power Relay (4PDT)
×1
12 Volt SMPS
×1
Grove - 2-Channel SPDT Relay
Seeed Studio Grove - 2-Channel SPDT Relay
×1
5 Volt SMPS
×1
Toggle Switch, (On)-Off-(On)
Toggle Switch, (On)-Off-(On)
×1
Raspberry Pi 3 Model B
Raspberry Pi 3 Model B
×1
Camera Module V2
Raspberry Pi Camera Module V2
×1
Micro SD card
×1
Micro-USB to USB Cable (Generic)
Micro-USB to USB Cable (Generic)
×1
Heat sink
×1
1 HP Water Pump
×1
Steel Box Pipe
×1
Water Tank (200 L)
×1
PVC Plastic Pipe
×1
4-Way Fogger
×1
Banner Flex
×1
Tee Joint
×1
Micro Tubing Pipe
×1
Wall Fix lamp
×1
Elbow
×1
Cable Tie, Double Sided
Cable Tie, Double Sided
×1

Software apps and online services

Arduino IDE
Arduino IDE
Raspbian
Raspberry Pi Raspbian
OpenCV
OpenCV

Hand tools and fabrication machines

Welding Machine
Cut-Off Machine
Soldering iron (generic)
Soldering iron (generic)
Solder Wire, Lead Free
Solder Wire, Lead Free
Laser cutter (generic)
Laser cutter (generic)

Story

Read more

Custom parts and enclosures

Smart Disinfection and Sanitation Tunnel 3D Model

Schematics

Smart Disinfection and Sanitation Tunnel

Circuit Diagram - fritzing file

Code

Arduino Code Tunnel

C/C++
/*
 * Smart Disinfection and Sanitation Tunnel
 */
 
int relayPin = 12;                // choose the pin for the Relay Pin

int inputPin = 2;               // choose the input pin (for PIR sensor)
int inputPin2 = 3;               // choose the input pin (for PIR sensor 02)

int pirState = LOW;             // we start, assuming no motion detected
int val = 0;                    // variable for reading the pin status
int val2 = 0;                    // variable for reading the pin status

 
void setup() {
  pinMode(relayPin, OUTPUT);      // declare Relay as output
  pinMode(inputPin, INPUT);     // declare PIR sensor as input
  pinMode(inputPin2, INPUT);  
  Serial.begin(9600);
}
 
void loop(){
  val = digitalRead(inputPin);  // read input value
  val2 = digitalRead(inputPin2);  // read input value
  if (val == HIGH || val2 == HIGH) {            // check if the input is HIGH
    digitalWrite(relayPin, HIGH);  // turn Relay ON
    if (pirState == LOW) {
      // we have just turned on
      Serial.println("Motion detected!");
      // 15 sec delay
      delay(15000);
      // We only want to print on the output change, not state
      pirState = HIGH;
    }
  } else {
    digitalWrite(relayPin, 0); // turn Relay OFF
    if (pirState == HIGH){
      // we have just turned of
      Serial.println("Motion ended!");
      // We only want to print on the output change, not state
      pirState = LOW;
    }
  }
  
}

main.py

Python
import cv2.cv as cv
from datetime import datetime
import time
import sys
import datetime



count=0

class MotionDetector():

    def onChange(self, val): #callback when the user change the ceil
        self.ceil = val

    def __init__(self,ceil=8, doRecord=True, showWindows=True):
        self.writer = None
        self.font = None
        self.doRecord=doRecord #Either or not record the moving object
        self.show = showWindows #Either or not show the 2 windows
        self.frame = None

        self.capture=cv.CaptureFromCAM(0)
        self.frame = cv.QueryFrame(self.capture) #Take a frame to init recorder
        if doRecord:
            self.initRecorder()

        self.frame1gray = cv.CreateMat(self.frame.height, self.frame.width, cv.CV_8U) #Gray frame at t-1
        cv.CvtColor(self.frame, self.frame1gray, cv.CV_RGB2GRAY)

        #Will hold the thresholded result
        self.res = cv.CreateMat(self.frame.height, self.frame.width, cv.CV_8U)

        self.frame2gray = cv.CreateMat(self.frame.height, self.frame.width, cv.CV_8U) #Gray frame at t

        self.width = self.frame.width
        self.height = self.frame.height
        self.nb_pixels = self.width * self.height
        self.ceil = ceil
        self.isRecording = False
        self.trigger_time = 0 #Hold timestamp of the last detection

        if showWindows:
            cv.NamedWindow("Image")
            #cv.CreateTrackbar("Mytrack", "Image", self.ceil, 100, self.onChange)

    def initRecorder(self): #Create the recorder
        codec = cv.CV_FOURCC('D', 'I', 'V', 'X')
        #codec = cv.CV_FOURCC("D", "I", "B", " ")
        self.writer=cv.CreateVideoWriter(datetime.now().strftime("%b-%d_%H:%M:%S")+".avi", codec, 15, cv.GetSize(self.frame), 1)
        #FPS set at 15 because it seems to be the fps of my cam but should be ajusted to your needs
        self.font = cv.InitFont(cv.CV_FONT_HERSHEY_SIMPLEX, 1, 1, 0, 2, 8) #Creates a font

    def run(self):
	global count
        started = time.time()
        while True:

            curframe = cv.QueryFrame(self.capture)
            instant = time.time() #Get timestamp o the frame

            self.processImage(curframe) #Process the image

            if not self.isRecording:
                if self.somethingHasMoved():
                    self.trigger_time = instant #Update the trigger_time
                    if instant > started +5:#Wait 5 second after the webcam start for luminosity adjusting etc..
                        print "Human Detected"
			

			
    			count += 1
			print(count/2)

			
			orig_stdout = sys.stdout
			f = open('out.txt', 'a+')
			sys.stdout = f


			print(count/2)
	
			sys.stdout = orig_stdout
			f.close()

			#timestamp log
			orig_stdout = sys.stdout
			f = open('log.txt', 'a+')
			sys.stdout = f

			
			timestampc =('Timestamp: {:%Y-%b-%d %H:%M:%S}'.format(datetime.datetime.now()))
			
			print(timestampc+'   Log Entry : 1')
	
			sys.stdout = orig_stdout
			f.close()

			

                        if self.doRecord: #set isRecording=True only if we record a video
                            self.isRecording = True
            else:
                if instant >= self.trigger_time +10: #Record during 10 seconds
                    print "Stop recording"
                    self.isRecording = False
                else:
                    cv.PutText(curframe,datetime.now().strftime("%b %d, %H:%M:%S"), (25,30),self.font, 0) #Put date on the frame
                    cv.WriteFrame(self.writer, curframe) #Write the frame

            if self.show:
                cv.ShowImage("Image", curframe)
                #cv.ShowImage("Res", self.res)

            cv.Copy(self.frame2gray, self.frame1gray)
            c=cv.WaitKey(1)
            if c==27 or c == 1048603: #Break if user enters 'Esc'.
                break

    def processImage(self, frame):
        cv.CvtColor(frame, self.frame2gray, cv.CV_RGB2GRAY)

        #Absdiff to get the difference between to the frames
        cv.AbsDiff(self.frame1gray, self.frame2gray, self.res)

        #Remove the noise and do the threshold
        cv.Smooth(self.res, self.res, cv.CV_BLUR, 5,5)
        element = cv.CreateStructuringElementEx(5*2+1, 5*2+1, 5, 5,  cv.CV_SHAPE_RECT)
        cv.MorphologyEx(self.res, self.res, None, None, cv.CV_MOP_OPEN)
        cv.MorphologyEx(self.res, self.res, None, None, cv.CV_MOP_CLOSE)
        cv.Threshold(self.res, self.res, 10, 255, cv.CV_THRESH_BINARY_INV)

    def somethingHasMoved(self):
        nb=0 #Will hold the number of black pixels

        for y in range(self.height): #Iterate the hole image
            for x in range(self.width):
                if self.res[y,x] == 0.0: #If the pixel is black keep it
                    nb += 1
        avg = (nb*100.0)/self.nb_pixels #Calculate the average of black pixel in the image
        #print "Average: ",avg, "%\r",
        if avg > self.ceil:#If over the ceil trigger the alarm
            return True
        else:
            return False

if __name__=="__main__":
    detect = MotionDetector(doRecord=False)
    detect.run()

Dashboard Files

PHP
No preview (download only).

Sanitation-Tunnel Android Source Code

Java
No preview (download only).

Sanitation-Tunnel Android App

Java
Demo App
No preview (download only).

Sanitation-Tunnel iOS Source Code

Swift
No preview (download only).

Smart Disinfection and Sanitation Tunnel

Credits

Yash Nayak

Yash Nayak

9 projects • 73 followers
Maker | Innovator | Technology Enthusiastic

Comments