스마트 UV-C & 열 살균 마스크 소독기: 아두이노 제어 DIY
부품 및 소모품
Seeed Grove 적외선 온도 센서
×
1
아두이노 우노
×
1
Seeed 베이스 실드 V2
×
1
Seeed Grove 조도 센서 (P) v1.1
×
1
Adafruit 쿼드 알파뉴메릭 디스플레이 0.54" 백색 I2C 백팩
×
1
Seeed 12mm 돔 푸시 버튼
×
1
피에조 스피커
×
1
Seeed 월 어댑터 12VDC 1.2A
×
1
프로젝트 개요
마스크 소독 장치
UV-C / 열 복합, 아두이노 제어, 코로나바이러스(SARS-CoV-2)용 마스크 소독기
본 프로젝트는 CC BY-NC-SA (저작자표시-비영리-동일조건변경허용) 라이선스로 공개됩니다.
면책: 이 문서는 '선의의 사마리아인 법' 하에 제공됩니다.
원문: needlab.org
소개
FFP1/FFP2 마스크는 감염병 시 필수 보호구 이나 일회용입니다. 위기 시 재사용이 불가피해 소독 방법이 필요합니다(참고 1). 병원 등에서는 UVGI(자외선 살균 조사)와 열을 활용하나, 취약 계층은 접근 어렵습니다. SARS-CoV-2는 수술용 마스크 표면에서 7일 후에도 생존 가능(참고 2).
본 프로젝트는 저비용, 휴대 가능, 쉽게 재현 가능 한 UVGI + 건열 소독 장치를 만드는 것이 목표입니다.
DIY 제작 가이드
장치 구성도
온도 유지: 65±5°C
램프: UV-C 파장 필수
소독 주기: 최소 30분 (마스크 열화 방지 위해 30분 초과 권장 안 함)
장치 치수
초기 가열 테스트
가열 시스템 제작
지름 22cm 프라이팬(인덕션 겸용), 손잡이 제거
프라이팬 내부를 알루미늄 호일로 덮어 UV-C 반사
박스 바닥 중앙에 지름 20cm 구멍 뚫기
금속 홀더 4개로 프라이팬 고정 (나무와 접촉 방지 → 열효율 저하 예방)
중요: 프라이팬이 박스 나무에 닿지 않게 홀더 형상과 구멍 크기 정확히 맞출 것.
상부 커버 제작
UV-C 시스템
수족관용 살균기 키트(11W UV-C 전구)에서 전구 추출해 상부 커버 양끝에 고정. 지퍼 타이와 부드러운 패드로 고정, 상부 표면 알루미늄 호일로 반사 강화. 크리스탈 튜브 없으면 유리는 UV-C 차단하므로 사용 불가. 다른 UV-C 램프 소스 활용 가능.
⚠️ 경고: UV-C 방사선 위험
UV-C는 눈과 피부에 매우 위험합니다. 상부 커버가 닫혔을 때만 UV-C 켜지고, 열리면 즉시 꺼지도록 인터록 필수.
Horror Coder 님의 댓글 조언 추가: "가시광선은 전체 방출의 3~4%에 불과하므로 눈으로 확인 불가. 10배 밝기 라이트로 박스 내부 조명 후 완전 암실에서 박스 주변 빛 샘 여부 확인 필수. 모든 구멍 막고 폼 가스켓/테두리로 누출 차단 후 위 방법으로 재검증."
내부 면 알루미늄 호일 마감
양면 테이프로 고정, 가장자리는 덕트 테이프로 마감. 측면과 상부 반사로 살균 효율 증대.
마스크 거치용 와이어 랙 제작
구리 연선 30mm 간격으로 랙 제작, 바닥에서 120mm 높이. 앞뒤 면 작은 구멍에 와이어 통과해 고정.
아두이노 및 센서 설정
아두이노 개요
자재 상세 (구매 링크 포함)
Arduino UNO Rev3
Grove Base Shield V2
Grove 적외선 온도 센서
Grove 조도 센서 (P)
푸시 버튼
피에조 스피커
쿼드 알파뉴메릭 디스플레이 (Adafruit 2157)
12VDC 월 어댑터
온도/조도 센서 연결
참고: 아두이노 온도 센서 벤치마킹
아두이노 제어 상태 머신
INIT: 온도 표시. 임계값(70°C) 도달 대기. 버튼 누르면 COUNT 진입.
COUNT: 남은 시간(30→0분)과 온도 표시. 온도 저하 또는 UV 꺼짐 시 ERR 전환. 1초마다 중간 점 깜빡임.
END: 정상 완료. 스피커 알림. 버튼으로 INIT 복귀.
ERR: 오류 상태(UV off/온도 저하). 스피커 알림. 버튼으로 INIT 복귀.
알람 조건: ① ERR 상태 ② 과열(75°C 초과) → 특수 톤 + 디스플레이 메시지.
아두이노 소스 코드
전체 코드: pastebin.com/zgK7zfMh
필수 외부 라이브러리:
사용자 매뉴얼
박스를 인덕션(또는 저항 히터) 호브 위에 올림.
아두이노 전원 ON.
박스 닫고 인덕션 70~80% 출력으로 가열.
60°C 도달 시 출력 30%로 낮춤.
박스 열고 마스크 넣고 닫음.
버튼 눌러 시작 → 남은 시간 30분 표시.
시간 00분 되면 스피커 알림.
새 사이클은 버튼 눌러 INIT으로 복귀.
참고: COUNT 상태 시 타이머/온도 사이 점이 1초 주기 깜빡임.
온도 사이클 그래프
바이러스 열 불활성화 근거
습열(100°C 미만) 살균은 파스퇴르 시대부터 알려짐. 건열로 SARS-CoV 불활성화 보고: 56°C 30-90분 상당, 65°C 20-60분 거의 완전, 75°C 30-45분 완전 불활성화(참고 7,8). 최신 연구: SARS-CoV-2 56°C 30분 또는 70°C 5분 후 감염력 소실(참고 2). 마스크 기능 저하 고려해 65°C 30분 프로토콜 채택.
마스크 소독 프로토콜 선행 연구
인플루엔자 바이러스: UVGI ~1 J/cm², 또는 65±5°C 습열 3시간으로 마스크 소독 효과 확인(참고 10,11).
코로나바이러스 마스크 소독 연구는 없으나, 인플루엔자도 ssRNA 바이러스라 유사 효과 기대.
추천 소독 절차
개인화, 소독 횟수 카운트, 포장 방법 등은 네브래스카 의대 N95 UVGI 재사용 프로세스 논문 참고 권장.
결론
수집된 증거와 기술적 세부사항 바탕으로 UV-C 조사 + 65±5°C 건열 30분 프로토콜 확정. 가열/조도 도달 시간 포함 카운트. 단독으로도 충분하나 동시 작용으로 안전성 강화.
안전 주의사항
UV-C는 피부/눈 손상 유발. 박스 닫혔을 때만 점등.
가열 후 금속 부품 화상 주의.
면책 조항
과학적 증거 기반이나, 본 장치로 SARS-CoV-2 불활성화 검증된 바 없으며 마스크 여과 성능 영향도 사전 평가 불가. 사용은 자유 결정에 따름.
차기 버전(V2) 계획
내부 확대(더 많은 마스크 수납)
CNC 밀링/레이저 커터 파일 제공
가열 방식 3종 선택: 인덕션, 전기 히터, 적외선 복사(PID 제어 포함)
2×16 LCD 디스플레이로 HMI 개선
다중 모드: 열+UV-C, 열만, UV-C만
다양한 온도 센서 선택 지원
업데이트 내역
6월 11일: V2로 12개 FFP2/N95 마스크 동시 소독 가능. OPT 1등 수상, 모로코 대학과 현지 생산 협력 중.
9월 2일: V2 프로젝트 Hackaday 공개: 링크
팀
Jean Noel Lefebvre, Daniel Moreno, Dr. Alejandra Duque, Dr. Felipe Gutiérrez Arango, Jason Knight, Maria Isabel Velez Isaza, Sameera Chukkapalli.
#COVID19DetectProtect
원문: needlab.org
참고문헌
CDC - N95 연장 사용/제한적 재사용 가이던스 (2019)
Chin et al. - SARS-CoV-2 환경 안정성 (medRxiv, 2020)
Tseng & Li - UVGI 표면 바이러스 불활성화 (JOEH, 2007)
Hackerfarm - NUKEMETER UV-C 강도 측정 (2020)
van Doremalen et al. - SARS-CoV-2 에어로졸/표면 안정성 (NEJM, 2020)
Kariwa et al. - SARS-CoV 불활성화 조건 (Jpn J Vet Res, 2004)
Duan et al. - SARS-CoV 열/UV 민감도 (Biomed Environ Sci, 2003)
Darnell et al. - SARS-CoV 불활성화 (J Virol Methods, 2004)
Ansaldi et al. - SARS-CoV/인플루엔자/RSV 소독제/UV 저항성 (2004)
Mills et al. - UVGI로 인플루엔자 오염 N95 소독 (Am J Infect Control, 2018)
Lore et al. - 인플루엔자 오염 마스크 3가지 소독법 비교 (Ann Occup Hyg, 2012)
Lindsley et al. - UVGI가 N95 여과 성능/구조에 미치는 영향 (JOEH, 2015)
Viscusi et al. - N95 5가지 소독법 평가 (Ann Occup Hyg, 2009)
Bergman et al. - N95 다중(3회) 소독 처리 평가 (J Eng Fiber Fabr, 2010)
Kampf et al. - 코로나바이러스 표면 생존 및 생물학적 제제 불활성화 (J Hosp Infect, 2020)
코드
TheBox V1 (C/C++)
/* Author: Jean Noel Lefebvre - www.ootsidebox.fr - March 31, 2020 */
#include <Wire.h>
#include "Adafruit_LEDBackpack.h"
#include <math.h>
#include <Metro.h>
#define LIGHT_SENSOR A2
#define SUR_TEMP_PIN A0
#define OBJ_TEMP_PIN A1
#define BUZZER 3
#define BP 2
#define SEUIL_TEMP 59
#define HIGH_TEMP 75
#define SEUIL_LIGHT 60
#define TIMER 30
float temp_calibration = 0;
float objt_calibration = 0.000;
float temperature_range = 10;
float offset_vol = 0.014;
float tempValue = 0, objtValue = 0, current_temp = 0, temp = 0, temp1 = 0, temp2 = 0;
unsigned int temp3 = 0;
const float reference_vol = 0.500;
unsigned char clear_num = 0;
float R = 0, voltage = 0;
long res[100] = { /* 서미스터 룩업 테이블 생략 */ };
float obj[13][12] = { /* 객체 온도 보정 테이블 생략 */ };
int Light; float Heat; int Timer = 0; int Minute = 59;
Adafruit_AlphaNum4 alpha4 = Adafruit_AlphaNum4();
Metro ledMetro = Metro(1000);
enum States { INIT, COUNT, END, ERR };
int Automate = INIT;
bool TemperatureOK = false, LightOK = false;
void setup() {
pinMode(BP, INPUT_PULLUP);
Serial.begin(9600);
analogReference(INTERNAL);
alpha4.begin(0x70);
alpha4.clear(); alpha4.writeDisplay();
PrintLed(alpha4, "TboX");
tone(3, 3000, 500); delay(1000);
Automate = INIT;
}
void loop() {
static int Point = 1;
float T1 = measureSurTemp();
float T2 = measureObjectTemp();
Heat = T1;
if (ledMetro.check() == 1) {
#ifndef TEST
if (Automate == COUNT) #endif {
Point = !Point;
if (--Minute == 0) { Minute = 59; if (Timer) Timer--; PrintSensors(); }
}
if (Automate == END) tone(3, 3000, 100);
if (Automate == ERR) tone(3, 300, 200);
}
#ifdef TEST TemperatureOK = true; #else
TemperatureOK = (Heat >= SEUIL_TEMP); #endif
Light = analogRead(LIGHT_SENSOR) / 10;
LightOK = (Light >= SEUIL_LIGHT);
if (Heat >= HIGH_TEMP) { tone(3, 300, 200); delay(500); }
switch (Automate) {
case INIT:
Timer = 0;
if (!digitalRead(BP) && TemperatureOK) { Automate = COUNT; Timer = TIMER; tone(3, 3000, 500); }
else if (!digitalRead(BP) && !TemperatureOK) { PrintLed(alpha4, "lowT"); tone(3, 300, 200); }
else PrintLedVal(alpha4, Timer, (int)Heat, Point);
break;
case COUNT:
if (Timer == 0) Automate = END;
if (!LightOK || !TemperatureOK) Automate = ERR;
PrintLedVal(alpha4, Timer, (int)Heat, Point);
break;
case END:
if (!digitalRead(BP)) Automate = INIT;
PrintLed(alpha4, "END.");
break;
case ERR:
if (!digitalRead(BP)) Automate = INIT;
PrintLed(alpha4, "Err.");
break;
}
}
// 온도 측정, 디스플레이 출력 등 헬퍼 함수 생략 (원문 참조)
라이브러리 저장소
회로도