Project tutorial
UV-C Sterilizer

UV-C Sterilizer © CC BY-NC-SA

Build a sterilizer using a UV-C lamp and a 3D printed enclosure!

  • 7 views
  • 0 comments
  • 0 respects

Components and supplies

Necessary tools and machines

3drag
3D Printer (generic)

Apps and online services

About this project

During this pandemic, it has become extremely important to make sure that we take all the necessary steps to keep this coronavirus away from us. Since the vaccines are still under development, the only way to stop the virus is to kill it. The only proven method to kill most of the viruses and germs is by using 'UVC Germicidal Lamp'. Enough exposure to UV-C radiation causes damage to DNA and RNA of the virus so they can't replicate, effectively killing or inactivating a virus. There are several reports claiming the effectiveness of UVC radiation on the new COVID-19. Few big companies have even launched their own UVC sterilizers. So why not make my own!

In this tutorial, I will be showing you how I built a sterilizer using a UVC lamp and a 3D printed enclosure. Using this sterilizer, you can sterilize your mask, mobile, and other small objects. This project is inspired by UVClean by Henry Mayne.

Let's get started!

Step 1: The Plan

Disclaimer: Overexposure to UVC radiation can cause permanent damage to skin and eyes. Take proper care while working with it. This project involves working with AC mains electricity as well which can be lethal. Proceed only if you know what you are doing!

The plan is very simple. Build a box of some kind and put the UVC lamp in it. I designed the enclosure in Fusion 360. It is divided into 3 parts. The uppermost part houses all the electronics and a UVC lamp. One part is the region where the radiation will occur and the last part is the drawer which will hold the objects to be sterilized.

As already stated, it is not a good idea for us to get exposed to UVC radiation frequently. Since the lamp will be in an enclosure made up of plastic which may absorb most of the radiation and prevent it from reaching us, there is a slight chance of radiation leaking through it. I'm not an expert on this so it is better to be safe. I will be using aluminum tape to cover the inside of the enclosure where the light will hit. This will also help in reflecting the light evenly. A magnetic reed switch will be used as an extra step to safety such that the lamp will turn/remain ON only when/till the door is closed.

Everything will be controlled using an Arduino Nano. There will be two modes of operation. First will be Manual Mode wherein you have to manually turn OFF the lamp. The second one will be a Timer Mode wherein the lamp will be turned ON for a set amount of time. A menu will be created and displayed on an OLED display. The menu can be controlled using a rotary controller. Thanks to Henry Mane all the hard work of creating a menu was already done. I figured out how the code works and modified it to suit my need.

Step 2: Things You Will Need

1x Arduino Nano

1x 11W UVC Lamp

1x 11W Electronic Ballast

1x 5V/500mA PCB SMPS

1x Fuse Holder

1x 5V SPDT Relay

1x Rotary Encoder

1x 0.96" OLED (I2C)

1x Piezo Buzzer

1x Reed Switch (NO)

1x Neodymium Magnet

1x prototyping board

2x 2-pin Screw Terminal

1x 2N2222 NPN Transistor

1x 1k Resistor

Step 3: 3D Printing

You don't have to 3D print the enclosure. You can use other ways to make a box. I'm not so good at building mechanical stuff. So, I let my printer do all the hard work. These are pretty big parts and so the overall printing process will take approximately 2 to 3 days to complete. The parts can be printed without any support if printed in correct orientation.

I have designed it in Fusion 360 and all the STL files are attached here.

Step 4: Electronics

I have attached the circuit diagram. The connections are very simple and can be easily soldered onto a prototyping board. But I am currently switching over from EasyEDA to Kicad.and wanted to design my first PCB in it. Also, I have been using JLCPCB for a while now but this time I wanted to try the Make-In-India (MII) service from LionCircuits, an Indian PCB Manufacturer. Click here to download the Gerber file.

Placing an order is very easy. Upload your Gerber files and check the DFM Summary to make sure that you have provided all the necessary (and correct) files. Once you are happy, make the payment. You can also use the 'Message' section to get your doubts cleared immediately.

Gather all the components and start soldering! Double-check your connections especially the AC Mains ones for any shorts. It is a good practice to keep the high voltage and low voltage connections separated.

Step 5: Putting Things Together

Stick the clamps on the inside of the lid. The two clamps should be in a straight line or else the tube won't fit.

Cover the inside portion of the enclosure using aluminum tape.

Stick the control panel to the control box using superglue as shown in the picture.

Insert the M3x4mm threaded inserts in the lid using a soldering iron.

Stick the reed switch on the inside of the front side of the lid and a small neodymium magnet on the inside of the drawer such that when the drawer is fully closed the reed switch and magnet lineup thus closing the contacts.

Attach the OLED display and rotary encoder to the front panel as shown. I have broken quite a few OLED displays while screwing them. So this time I printed a holder and attached the OLED to it using pins.

Place the ballast and PCB on top of the lid using some double-sided tape and carefully route the cables to them. I have added a fuse just to be safe. Close all the electronics by placing the cover on top of it and screwing it to the lid using M3 screws.

Stick the handle in place.

Step 6: Enjoy!

That's it! Plug it in into your wall outlet, place the things you want to sanitize in the drawer, and turn it ON the lamp using any two modes.

Thank you for sticking to the end. I hope you all love this project and learned something new today. Let me know if you make one for yourself. Subscribe to my YouTube channel for more such projects.

Code

UV-C Sterilizer CodeArduino
/*
This Project is inspired by UVClean by Henry Mayne
https://www.hackster.io/henry-mayne/diy-ultraviolet-sterilization-device-uvclean-7d31b1
All the hard work of creating a menu has been done by him. I have just modified his code to fit my needs! 
*/

#define CLK 3
#define DT 4
#define SW 5
#define BULB 6
#define BUZZER 8
#define REED 7

int counter = 0;
int state;
int Laststate;
int menuID = 1;
int menuChange = 0;
int leave = 0;
int minutes = 1;
int timeSelect = 1;
int seconds10 = 0;
int seconds1 = 0;
unsigned long startMillis;

#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>

#define SCREEN_WIDTH 128 // OLED display width, in pixels
#define SCREEN_HEIGHT 64 // OLED display height, in pixels

#define OLED_RESET     4 
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);

void setup(){
  pinMode(BULB, OUTPUT);
  pinMode(CLK,INPUT);
  pinMode(DT,INPUT);
  pinMode(SW,INPUT_PULLUP);
  pinMode(BUZZER, OUTPUT);
  pinMode(REED, INPUT_PULLUP);
  Serial.begin(9600);
  Laststate = digitalRead(CLK);
  digitalWrite(BULB, LOW);
  
  if(!display.begin(SSD1306_SWITCHCAPVCC, 0x3C)){ 
    Serial.println(F("SSD1306 allocation failed"));
    for(;;); // Don't proceed, loop forever
  }
 
  display.clearDisplay();
  display.setTextSize(2);             
  display.setTextColor(SSD1306_WHITE);       
  display.setCursor(0,0);             
  display.println(F(" MAIN MENU"));
  display.setTextSize(1);
  display.println(F(""));
  display.println(F("-> Manual Mode"));
  display.println(F(""));
  display.println(F("   Timer Mode"));  
  display.println(F(""));
  display.println(F("   Safety"));           
  display.display();  
}

void loop(){
  state = digitalRead(CLK);
  if(state != Laststate){
    if(digitalRead(DT) != state){
      counter++;
    }
    else{  
      counter--;
    }
  }
  if(digitalRead(SW) != 1){
    counter = 0;
    tone(BUZZER, 3000, 50);
    }
    
    Laststate = state;
    if(counter == 2){
      counter = 0;
      menuID++;
      menuChange = 1;
    }

    if(counter == -2) {
      counter = 0;
      menuID--;
      menuChange = 1;
    }
    
    if(digitalRead(SW) != 1) {
      tone(BUZZER, 3000, 50);
      menuChange = 1;
      switch(menuID) {
        case 1:
        menuID = 11;
        break;
        case 2:
        menuID = 21;
        break;
        case 3:
        menuID = 31;
        break;
        case 11:
        menuID = 101;
        break;
        case 12:
        menuID = 1;
        break;
        case 21:
        menuID = 210;
        break;
        case 22:
        menuID = 220;
        break;
        case 23:
        menuID = 1;
        break;
        case 31:
        menuID = 3;
        break;
        case 210:
        menuID = 21;
        timeSelect = 1;
        break;
        case 211:
        menuID = 21;
        timeSelect = 2;
        break;
        case 212:
        menuID = 21;
        timeSelect = 3;
        break;
      }
      delay(250);
    }

    if(menuID == 0 || menuID == 4 || menuID == 10 || menuID == 13 || menuID == 20 || menuID == 24 || menuID == 213 || menuID == 209 ){
      switch(menuID){
        case 0:
        menuID = 3;
        break;
        case 4:
        menuID = 1;
        break;
        case 10:
        menuID = 12;
        break;
        case 13:
        menuID = 11;
        break;
        case 20:
        menuID = 23;
        break;
        case 24:
        menuID = 21;
        break;
        case 30:
        menuID = 31;
        break;
        case 32:
        menuID = 31;
        break;
        case 213:
        menuID = 210;
        break;
        case 209:
        menuID = 212;
        break;
      }
      menuChange = 1;
    }
    
    if(menuChange == 1){
      switch(menuID){
        case 1:
        menu1();
        menuChange = 0;
        break;
        
        case 2:
        menu2();
        menuChange = 0;
        break;
        
        case 3:
        menu3();
        menuChange = 0;
        break;
        
        case 11:
        menu11();
        menuChange = 0;
        break;
        
        case 101:
        if(digitalRead(REED) == 0){
        digitalWrite(BULB, HIGH);
        Serial.println("BULB ON");
        while(leave == 0 && digitalRead(REED) == 0) {
          menu101();
          if(digitalRead(SW) != 1){
            leave = 1;
          }
          else if(digitalRead(REED) != 0){
            leave = 1;
            errorMessage;
          }
         }
        }
        else{
          errorMessage();
        }
        tone(BUZZER, 3000, 1000);
        digitalWrite(BULB, LOW);
        Serial.println("BULB OFF");
        leave = 0;
        menuID = 11;
        menuChange = 1;
        delay(500);
        break;
        
        case 12:
        menu12();
        menuChange = 0;
        break;
        
        case 21:
        menu21();
        menuChange = 0;
        break;
        
        case 220:
        minutes = timeSelect;
        seconds10 = 0;
        seconds1 = 0;
        if(digitalRead(REED) == 0){
        digitalWrite(BULB, HIGH);
        Serial.println("BULB ON");
        
        while(leave == 0 && digitalRead(REED) == 0) {
          display.clearDisplay();
          display.setTextSize(2);
          display.setTextColor(SSD1306_WHITE);
          display.setCursor(0,0);
          display.println(F("CAUTION:"));
          display.setTextSize(1);
          display.println(F("UVC irradiation in   progress"));
          display.setCursor(0,34);
          display.setTextColor(SSD1306_BLACK, SSD1306_WHITE);
          display.println(F("    TIME REMAINING:  "));
          display.setTextColor(SSD1306_WHITE);
          display.setCursor(14,43);
          display.setTextSize(3);
          display.print(F(" "));
          display.print(minutes);
          display.print(F(":"));
          display.print(seconds10);
          display.print(seconds1);
          display.display();

          if(minutes == 0 && seconds10 == 0 && seconds1 == 0) {
            leave = 1;
          }
           
          if(seconds1 == 0) {
            seconds1 = 9;
            seconds10--;
          }
          else {
            seconds1--;
          }
          
          if(seconds10 == -1) {
            seconds10 = 5;
            minutes--;
          }
          if(digitalRead(REED) != 0){ 
            leave = 1;
            errorMessage();
          }
          startMillis = millis();
          while(millis() <= startMillis + 1000 && leave == 0) {
            if(digitalRead(SW) != 1) {
              leave = 1;
            }
          }  
        }
        }
        else{
          errorMessage();
        }
        tone(BUZZER, 3000, 1000);
        digitalWrite(BULB, LOW);
        Serial.println("BULB OFF");
        leave = 0;
        menuID = 21;
        menuChange = 1;
        delay(500);
        break;
        
        case 22:
        menu22();
        menuChange = 0;
        break;

        case 23:
        menu23();
        menuChange = 0;
        break;

        case 31:
        menu31();
        menuChange = 0;
        break;

        case 210:
        menu210();
        menuChange = 0;
        break;

        case 211:
        menu211();
        menuChange = 0;
        break;

        case 212:
        menu212();
        menuChange = 0;
        break;
      }
    }  
}

void menu1() {
  display.clearDisplay();
  display.setTextSize(2);            
  display.setTextColor(SSD1306_WHITE);        
  display.setCursor(0,0);             
  display.println(F(" MAIN MENU"));
  display.setTextSize(1);
  display.println(F(""));
  display.println(F("-> Manual Mode"));
  display.println(F(""));
  display.println(F("   Timer Mode"));          
  display.println(F("")); 
  display.println(F("   Safety"));          
  display.display(); 
}

void menu2() {
  display.clearDisplay();
  display.setTextSize(2);             
  display.setTextColor(SSD1306_WHITE);        
  display.setCursor(0,0);             
  display.println(F(" MAIN MENU"));
  display.setTextSize(1);
  display.println(F(""));
  display.println(F("   Manual Mode"));
  display.println(F(""));
  display.println(F("-> Timer Mode"));       
  display.println(F(""));
  display.println(F("   Safety"));          
  display.display();   
}

void menu3(){
  display.clearDisplay();
  display.setTextSize(2);             
  display.setTextColor(SSD1306_WHITE);        
  display.setCursor(0,0);             
  display.println(F(" MAIN MENU"));
  display.setTextSize(1);
  display.println(F(""));
  display.println(F("   Manual Mode"));
  display.println(F(""));
  display.println(F("   Timer Mode"));       
  display.println(F(""));  
  display.println(F("-> Safety"));          
  display.display(); 
}

void menu11() {
  display.clearDisplay();
  display.setTextSize(2);             
  display.setTextColor(SSD1306_WHITE);        
  display.setCursor(0,0);             
  display.println(F("MANUAL"));
  display.setTextSize(1);
  display.println(F("Press button to      turn the UVC lamp    ON/OFF"));
  display.println(F(""));
  display.setTextSize(2);
  display.setTextColor(SSD1306_BLACK, SSD1306_WHITE);
  display.print(F("START"));
  display.setTextColor(SSD1306_WHITE);
  display.println(F(" EXIT"));          
  display.display();  
}

void menu12() {
  display.clearDisplay();
  display.setTextSize(2);             
  display.setTextColor(SSD1306_WHITE);        
  display.setCursor(0,0);             
  display.println(F("MANUAL"));
  display.setTextSize(1);
  display.println(F("Press button to      turn the UVC lamp    ON/OFF"));
  display.println(F(""));
  display.setTextSize(2);
  display.print(F("START "));
  display.setTextColor(SSD1306_BLACK, SSD1306_WHITE);
  display.println(F("EXIT"));        
  display.display();
}

void menu21() {
  display.clearDisplay();
  display.setTextSize(2);            
  display.setTextColor(SSD1306_WHITE);       
  display.setCursor(0,0);             
  display.println(F("   TIMER"));
  display.setTextSize(1);
  display.println(F("Exposure time:"));
  display.setTextColor(SSD1306_BLACK, SSD1306_WHITE);
  display.print(timeSelect);
  display.println(" min");
  display.setTextSize(2);
  display.setTextColor(SSD1306_WHITE);
  display.println(F(""));
  display.print(F("START"));
  display.print(F(" EXIT"));
  display.display(); 
}

void menu22() {
  display.clearDisplay();
  display.setTextSize(2);             
  display.setTextColor(SSD1306_WHITE);       
  display.setCursor(0,0);             
  display.println(F("   TIMER"));
  display.setTextSize(1);
  display.println(F("Exposure time:"));
  display.print(timeSelect);
  display.println(" min");
  display.setTextSize(2);
  display.setTextColor(SSD1306_WHITE);
  display.println(F(""));
  display.setTextColor(SSD1306_BLACK, SSD1306_WHITE);
  display.print(F("START"));
  display.setTextColor(SSD1306_WHITE);
  display.print(F(" EXIT"));
  display.display(); 
}

void menu23() {
  display.clearDisplay();
  display.setTextSize(2);            
  display.setTextColor(SSD1306_WHITE);       
  display.setCursor(0,0);            
  display.println(F("   TIMER"));
  display.setTextSize(1);
  display.println(F("Exposure time:"));
  display.print(timeSelect);
  display.println(" min");
  display.setTextSize(2);
  display.setTextColor(SSD1306_WHITE);
  display.println(F(""));
  display.print(F("START "));
  display.setTextColor(SSD1306_BLACK, SSD1306_WHITE);
  display.print(F("EXIT"));
  display.display(); 
}

void menu31(){
  display.clearDisplay();
  display.setTextSize(2);            
  display.setTextColor(SSD1306_WHITE);        
  display.setCursor(0,0);             
  display.println("CAUTION");
  display.println("");
  display.setTextSize(1);
  display.print("UV-C Radiation can   cause damage to your skin and eyes");
  display.display();
}

void menu101(){
  display.clearDisplay();
  display.setTextSize(2);
  display.setTextColor(SSD1306_WHITE);
  display.setCursor(0,0);
  display.println(F("CAUTION:"));
  display.setTextSize(1);
  display.println(F("UVC irradiation in   progress"));
  display.setTextSize(2);
  display.println(F(""));
  display.print(F("   "));
  display.setTextColor(SSD1306_BLACK, SSD1306_WHITE); // Draw 'inverse' text
  display.println(F("STOP"));
  display.display();
}

void menu210(){
    display.clearDisplay();
    display.setTextSize(2);             
    display.setTextColor(SSD1306_WHITE);        
    display.setCursor(0,0);            
    display.println(F(""));
    display.setTextSize(1);
    display.println(F("Exposure time:"));
    display.setTextColor(SSD1306_BLACK, SSD1306_WHITE);
    display.println("1 min");
    display.setTextColor(SSD1306_WHITE);
    display.println("2 min");
    display.println("3 min");
    display.display(); 
}

void menu211(){
    display.clearDisplay();
    display.setTextSize(2);             
    display.setTextColor(SSD1306_WHITE);        
    display.setCursor(0,0);             
    display.println(F(""));
    display.setTextSize(1);
    display.println(F("Exposure time:"));
    display.setTextColor(SSD1306_WHITE);
    display.println("1 min");
    display.setTextColor(SSD1306_BLACK, SSD1306_WHITE);
    display.println("2 min");
    display.setTextColor(SSD1306_WHITE);
    display.println("3 min");
    display.display(); 
}

void menu212(){
    display.clearDisplay();
    display.setTextSize(2);             
    display.setTextColor(SSD1306_WHITE);        
    display.setCursor(0,0);             
    display.println(F(""));
    display.setTextSize(1);
    display.println(F("Exposure time:"));
    display.setTextColor(SSD1306_WHITE);
    display.println("1 min");
    display.println("2 min");
    display.setTextColor(SSD1306_BLACK, SSD1306_WHITE);
    display.println("3 min");
    display.display(); 
}

void errorMessage(){
  display.clearDisplay();
  display.setTextSize(2);
  display.setTextColor(SSD1306_WHITE);
  display.setCursor(0,0);
  display.println("CLOSE THE");
  display.println("DRAWER");
  display.display();
  delay(2000);
}
  

Custom parts and enclosures

lid.stl
lid.stl
clamp.stl
clamp.stl
ctrl+box.stl
ctrl%2Bbox.stl
drawer.stl
drawer.stl
handle.stl
handle.stl
knob.stl
knob.stl
main.stl
main.stl
ctrl+panel.stl
ctrl%2Bpanel.stl
oled_pin.stl
oled_pin.stl

Schematics

UVC Sterilizer Schematic

Comments

Similar projects you might like

Sorting Resistors the Lazy Way

Project tutorial by Federico Vivaldi

  • 15,069 views
  • 40 comments
  • 89 respects

Stop Sweaty Hands and Feet With Sweat Fighter!

Project tutorial by Cameron Coward

  • 4,698 views
  • 1 comment
  • 16 respects

Smart Glasses for Social Distancing

Project tutorial by Bilal Ahmed

  • 1,663 views
  • 1 comment
  • 2 respects

Mechanical 7-Segment Display

Project tutorial by Neeraj Rane

  • 1,462 views
  • 1 comment
  • 13 respects

Open Source Pulse Oximeter for COVID-19

Project tutorial by Arduino “having11” Guy

  • 40,077 views
  • 22 comments
  • 109 respects

ATtiny85 Mini Arcade: Snake

Project tutorial by Arduino “having11” Guy

  • 4,356 views
  • 7 comments
  • 23 respects
Add projectSign up / Login