スマート消毒および衛生トンネル
コンポーネントと消耗品
> |
| × | 1 | |||
| × | 1 | ||||
| × | 2 | ||||
| × | 1 | ||||
| × | 1 | ||||
| × | 1 | ||||
| × | 1 | ||||
| × | 1 | ||||
| × | 1 | ||||
| × | 1 | ||||
| × | 1 | ||||
| × | 1 | ||||
| × | 1 | ||||
| × | 1 | ||||
| × | 1 | ||||
| × | 1 | ||||
| × | 1 | ||||
| × | 1 | ||||
| × | 1 | ||||
| × | 1 | ||||
| × | 1 | ||||
| × | 1 | ||||
| × | 1 | ||||
| × | 1 |
必要なツールとマシン
| ||||
| ||||
| ||||
| ||||
|
アプリとオンラインサービス
> |
| |||
| ||||
|
このプロジェクトについて
はじめに
Smart Disinfection and Sanitation Tunnelは、トンネルを通過する人々を約15秒で最大限に保護するように設計されていることを示しています。これは、コミュニティがCOVID-19と戦うのに役立ちます。
このプロジェクトの主なアイデアは、COVID-19の蔓延を防ぐことができるトンネルを作ることです。
この消毒および衛生トンネルは、15秒以内に細菌から人々を消毒するために用意されています。
使用される消毒液は、次亜塩素酸ナトリウム(NaOCl)と水(H2O)の組み合わせで構成されています。消毒剤は不揮発性であるため、長期にわたる検証および殺菌作用を可能にし、表面を消毒します。
そこで、私はこのイニシアチブをとって、このスマート消毒および衛生トンネルを作成しました。このトンネルは12時間の期間で作られました。わずか15秒の時間で頭からつま先まで完全に消毒でき、使用する溶液は完全に無害です*。トンネルの総費用は約£です。 30,000または$ 400。 (修正後の費用)
<図>
<図>
どこで使用しますか?
- 食品市場
- オフィス
- ショッピングモール
- 空港
- バス停
- 鉄道駅
- 警察署
- 大学
- 病院
- コロニー
仕組み
1HPウォーターポンプマシンが各トンネルの側面に配置され、タンクから100リットルの水に0.4%の次亜塩素酸ナトリウム溶液が溶け込んでいます。機械は自動であるため、誰かがトンネルに入っているかどうかを感知します。誰かがトンネルに入ると、ウォーターポンプが15秒間始動します。ユーザーがそのトンネルを通過できるように、トンネル内に誰もいない場合は、水と電気を節約するためにポンプがオフになります。霧状の消毒スプレーは、少なくとも60分間(約*)、市民がバクテリアを捕まえるのを防ぎます。空気、露出した皮膚、人間の衣服を消毒します。
<図>
<図>
トンネルの側面には、200リットルの溶液用のプラスチックタンクと高圧配管システム用のポンプがあります。計算によると、ソリューションは8〜10時間で十分なはずです。防腐剤を節約するために入り口の上にモーションセンサーがあるので。 (トンネルに入る人によって異なる場合があります**)
フロー図 <図>
ハードウェアのセットアップ
私はフレームを金属製のプロファイルからレイアウトし、折りたたんで場所から場所へと移動できるようにしました。フレームがすべて終わったら、次の黙示録に備えて保管します。カバーはバナー(屋外広告に使用されます )によるものです。 )。バナーは、プラスチックのネクタイを備えた金属プロファイルで簡単に取り付けることができます。高速で、特別なスキルは必要ありません。
<図>モデルをチェックしてください-https://skfb.ly/6RGvZ
<図>4ウェイフォガーアセンブリに接続されているトンネルの側面には、200リットルの溶液用のプラスチックタンクと高圧パイプシステム用のポンプがあります。
<図> >トンネル全体にマイクロチューブパイプを使用して、噴霧器に溶液を供給しています。
<図> >内部には、接続可能な4つの4ウェイフォガーを備えた高圧パイプラインがあります。霧は衣服に跡を残さず、入ってくる人を完全に包み込み、手の届きにくい衣服のひだでもウイルスを破壊し、退出後しばらくの間保護します。
ソリューションとして、このプロジェクトでは認定ソリューションが使用されます。 (以下に添付されている証明書)
<図>4ウェイフォガー
- 排出率:30 LPH / 0.5 LPM(1フォガーの場合)
- 推奨圧力:45〜60 psi
- 平均液滴サイズ:65ミクロン(55〜60 psi)
- 必要なろ過:130ミクロン(120メッシュ)
- 必要なポンプ:40〜45メートルのヘッド
使用したその他のアクセサリ
<図> <図>
Arduinoを準備する
ウォーターポンプは、実際には赤外線を検出して動作します。人体が赤外線を反射するように人体がモーションセンサーに近づくと、モーションセンサーがこの赤外線を検出し、出力ピンを介してHIGH信号を送信します。このHIGH信号は、Arduinoによって読み取られます。したがって、ArduinoがHIGH信号を読み取ると、リレーモジュールにHIGH信号が送信されます。これは、リレーがオンになることを意味します。その結果、電源リレーがオンになり、ウォーターポンプが15秒間オンになります(Can変更されます)。同様に、ArduinoがLOW信号を読み取ると、リレーピンがLOWになり、その結果、ウォーターポンプはオフのままになります。
これでは、2つのPIRセンサーを使用して、いずれかが動きを感知すると、リレーが15秒間オンになります(変更可能)。
私の場合、このプロジェクトで使用したウォーターポンプのAmpere(A)定格は16Ampereであり、5Vリレーの最大負荷は10Ampereであるため、ウォーターポンプを制御するために5Vリレーをウォーターポンプで直接使用することはできません。 5Vリレーモジュールでもう1つのリレーを使用しました。これは12Vパワーリレーです。
<図>コード:
/ *
*スマート消毒および衛生トンネル
* /
int relayPin =12; //リレーピンのピンを選択します
int inputPin =2; //入力ピンを選択します(PIRセンサー用)
int inputPin2 =3; //入力ピンを選択します(PIRセンサー02の場合)
int pirState =LOW; //開始時に、モーションが検出されなかったと仮定します
int val =0; //ピンステータスを読み取るための変数
int val2 =0; //ピンステータスを読み取るための変数
void setup(){
pinMode(relayPin、OUTPUT); //リレーを出力として宣言します
pinMode(inputPin、INPUT); //センサーを入力として宣言します
pinMode(inputPin2、INPUT);
Serial.begin(9600);
}
void loop(){
val =digitalRead(inputPin); //入力値を読み取ります
val2 =digitalRead(inputPin2); //入力値を読み取ります
if(val ==HIGH || val2 ==HIGH){//入力がHIGHかどうかを確認します
digitalWrite(relayPin、HIGH); //リレーをオンにします
if(pirState ==LOW){
//オンにします
Serial.println( "モーションが検出されました!");
// 15秒の遅延
delay(15000);
pirState =HIGH;
}
} else {
digitalWrite(relayPin、0); //リレーをオフにします
if(pirState ==HIGH){
//オフにします
Serial.println( "モーションが終了しました!");
pirState =LOW;
}
}
}
プロジェクトの最終的な配線は少し面倒に見えますが、問題なく機能しました。
<図> >すべて配線した後、基本的なセンシングでテストし、リレーが作動していることを確認しました。
Raspberry Pi 3を準備します(オプション)
これはオプションです。データの分析を行い、このトンネルを使用している人の数を正確に数える必要がある場合に備えて。この部分を実装できます。
PIRセンサーや超音波センサーなどのいくつかの物理センサーでそれを数える方法はたくさんありますが、すべてのオッズを考えていると、これはより正確であることがわかりました。
PythonのOpenCVを使用して人体を検出し、アプリにデータを表示するために処理できるファイルにログを保存する機械学習モデルがあります。
Piカメラを接続する
- ラズベリーパイの電源を切ります
- USBモジュールとHDMIモジュールの間にカメラモジュールを配置します。
- (ゆっくりと)上に引っ張って黒いプラスチッククリップのロックを解除します
- カメラモジュールのリボンケーブルを挿入します(金属製のコネクタ反対側 RaspberryPiのイーサネット/ USBポートから4)
- 黒いプラスチッククリップをロックする
Piカメラを有効にする
- 実行
sudo raspi-config
- Raspberry Piソフトウェア構成ツールのメインメニューから[インターフェイスオプション](つまり、4番目のオプション)を選択します。 ENTERを押します。
-
カメラを有効にする
を選択します (つまり、5番目のオプション)メニューオプションを選択し、Enterキーを押します。
- 次のメニューで、右矢印キーを使用して
ENABLE
を強調表示します ENTERを押します。
Piカメラのテスト
次に、カメラのプレビューオーバーレイを開始して、Piカメラが正しくインストールされていることを確認します。オーバーレイが画面に表示されます。
- VNCViewerを使用してRaspberryPiに接続します。
- 次のコマンドを実行します:
raspistill -v -o test.jpg
Pi Cameraを正しくインストールすると、画面にレンダリングされたカメラからの映像が表示されます。
<図>
OpenCVのインストール
このリンクをたどってOpenCVをインストールしてください
https://www.learnopencv.com/install-opencv-4-on-raspberry-pi/
コード
次のコマンドを実行して、新しいスクリプトファイルを作成して開きます。
cd Desktop
sudo nano main.py
スクリプトをコピーして、作成した新しいファイルに貼り付けます。
import cv2.cv as cv
from datetime import datetime
import time
import sys
import datetime
count =0
class MotionDetector():
def onChange(self、val):ユーザーがceilを変更したときの#callback
self.ceil =val
def __init __(self、ceil =8、doRecord =True、 showWindows =True):
self.writer =None
self.font =None
self.doRecord =doRecord#移動するオブジェクトを記録するかどうか
self.show =showWindows# 2つのウィンドウを表示するかどうか
self.frame =None
self.capture =cv.CaptureFromCAM(0)
self.frame =cv.QueryFrame(self.capture)#フレームを取得しますレコーダーを初期化する
if doRecord:
self.initRecorder()
self.frame1gray =cv.CreateMat(self.frame.height、self.frame.width、cv.CV_8U)#Gray frame t-1で
cv.CvtColor(self.frame、self.frame1gray、cv.CV_RGB2GRAY)
#しきい値の結果を保持します
self.res =cv.CreateMat(self.frame。高さ、self.frame.width、cv.CV_8U)
self.frame2gray =cv.CreateMat(self.fra me.height、self.frame.width、cv.CV_8U)#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#最後の検出のタイムスタンプを保持
if showWindows :
cv.NamedWindow( "Image")
#cv.CreateTrackbar( "Mytrack"、 "Image"、self.ceil、100、self.onChange)
def initRecorder(self): #レコーダーを作成する
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は15に設定されています。これは、私のカムのfpsのようですが、ニーズに合わせて調整する必要があるためです
self.font =cv.InitFont (cv.CV_FONT_HERSHEY_SIMPLEX、1、1、0、2、8)#フォントを作成します
def run(self):
グローバルカウント
started =time.time()
Trueの場合:
curframe =cv.QueryFrame(self.capture)
instance =time.time()#フレームのタイムスタンプを取得します
self.processImage(curframe)#画像を処理します
self.isRecordingでない場合:
if self.somethingHasMoved():
self.trigger_time =Instant #trigger_timeを更新します
インスタント>が開始された場合+5:#ウェブサイトの開始から5秒後に輝度調整などを行います。
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 +'ログエントリ:1 ')
sys.stdout =orig_stdout
f.close()
if self.doRecord:#set isRecording =ビデオを録画する場合にのみTrue
self.isRecording =True
else:
if Instant> =self.trigger_time +10:#10秒間録画する
print "Sto precording "
self.isRecording =False
else:
cv.PutText(curframe、datetime.now()。strftime("%b%d、%H:%M:%S ")、(25,30)、self.font、0)#フレームに日付を入力
cv.WriteFrame(self.writer、curframe)#フレームを書き込む
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 enter'Esc '。
break
def processImage(self、frame):
cv.CvtColor(frame、self.frame2gray、cv.CV_RGB2GRAY)
#Absdiffでフレーム間の差を取得
cv.AbsDiff(self.frame1gray、self.frame2gray、self.res)
#ノイズを取り除き、しきい値を設定します
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.Thre shold(self.res、self.res、10、255、cv.CV_THRESH_BINARY_INV)
def somethingHasMoved(self):
nb =0#yの黒ピクセル数を保持します
range(self.height):#範囲内のxの穴の画像を反復します
range(self.width):
if self.res [y、x] ==0.0:#ピクセルが黒の場合it
nb + =1
avg =(nb * 100.0)/self.nb_pixels#画像内の黒ピクセルの平均を計算します
#print "Average:"、avg、 "%\ r "、
if avg> self.ceil:#ceilを超えるとアラームがトリガーされます
return True
else:
return False
if __name __ ==" _ main__ ":
detect =MotionDetector(doRecord =False)
detect.run()
ダウンロード-https://www.hackster.io/code_files/438321/download
それが完了したら、「CTRL + X」、「Y」、「Enter」の順に入力してファイルを保存します。次のコマンドを入力すると、スクリプトを実行できます。
python main.py
画面に画像が表示されるはずです。ビデオを表示して、必要に応じて、ターミナルのプログラムによる人員数を確認してください。
<図>ArduinoとRaspberryPi3用のMDFシートを使用してエンクロージャーを作成しました
<図>
デスクトップ/アプリのダッシュボードを作成する
ステップ1:Apacheをインストールする
apache2
をインストールします このコマンドを使用したパッケージ:
sudo apt install apache2 -y
ステップ2:PHPをインストールする
ApacheサーバーでPHPファイルを処理できるようにするには、最新バージョンのPHPとApache用のPHPモジュールをインストールする必要があります。これらをインストールするには、次のコマンドを入力します。
sudo apt install php libapache2-mod-php -y
次に、 Dashboard.zip
をダウンロードします :
cd / var / www / html
wget "https://hacksterio.s3.amazonaws.com/uploads/attachments/1097966/Dashboard.zip"
解凍をインストールします:
sudo apt-get install unzip
ZIPファイルからファイルを抽出します:
ddashboard.zipを解凍
次に、ブラウザを保存して更新します。表示されるはずです
<図> <図>
RaspberryPiをワイヤレスアクセスポイントとして設定する
このリンクをたどってくださいhttps://www.raspberrypi.org/documentation/configuration/wireless/access-point.md
注:ワイヤレスアクセスポイントにSanitizingTunnelという名前を付けます
interface =wlan0
driver =nl80211
ssid =SanitizingTunnel
hw_mode =g
channel =7
wmm_enabled =0
macaddr_acl =0
auth_algs =1
ignore_broadcast_ssid =0
wpa =2
wpa_passphrase =SecretPassword
wpa_key_mgmt =WPA-PSK
wpa_pairwise =TKIP
rsn_pairwise =CCMP
<図>
それでは、アプリの作成を始めましょう。
Androidアプリ:
前提条件:Android Studio
ここから直接コードをダウンロードできます。
必要に応じて、ラズベリーパイのIPアドレスなどのクレデンシャルを変更します。
<図>
iOSアプリ:
前提条件:XCode
ここから直接コードをダウンロードできます。
必要に応じて、ラズベリーパイのIPアドレスなどのクレデンシャルを変更します。
<図>
使用した化学溶液
消毒トンネルには、100リットルの水に0.4%の次亜塩素酸ナトリウム溶液が含まれています。
<図>更新 -有害な化学物質を使用しているというコメントをたくさん見ました。
だから、私はこの化学物質を私に供給していたベンダーから情報を収集するだけです。それで彼は私がこのトンネルで使用している化学物質はRaman&WeilPvtからのものであると私に言いました。 Ltdと彼らは「宣言 " Bode Chemie Germany から 、 COVID-19 に対する有効性について 。
公式リンク-http://ramanweil.com/pdf/Declaration%20from%20Bode%20Chemie%20Germany%20on%20efficacy%20against%20COVID%2019.pdf
<図>
すべてをまとめる
最後に、トンネルの電源を入れて、すべてのルーチンとアプリが計画どおりに機能していることを確認します。
<図> <図> <図>
費用 <図>
リンク-https://docs.google.com/spreadsheets/d/1jt-hy8N8IwuQnaLYt-25BywdlREkEhp5zjAfYC6eGqw/edit?usp =sharing
コード
- Arduinoコードトンネル
- main.py
- ダッシュボードファイル
- サニテーション-TunnelAndroidソースコード
- サニテーション-TunnelAndroidアプリ
- サニテーション-トンネルiOSソースコード
Arduinoコードトンネル C / C ++
/ **スマート消毒および衛生トンネル* / int relayPin =12; //リレーPinintのピンを選択しますinputPin =2; //入力ピンを選択します(PIRセンサー用)int inputPin2 =3; //入力ピンを選択します(PIRセンサー02の場合)int pirState =LOW; //動きが検出されないと仮定して開始しますintval =0; //ピンステータスを読み取るための変数intval2 =0; //ピンステータスを読み取るための変数voidsetup(){pinMode(relayPin、OUTPUT); //リレーを出力として宣言しますpinMode(inputPin、INPUT); // PIRセンサーを入力として宣言しますpinMode(inputPin2、INPUT); Serial.begin(9600);} void loop(){val =digitalRead(inputPin); //入力値を読み取りますval2 =digitalRead(inputPin2); //入力値を読み取りますif(val ==HIGH || val2 ==HIGH){//入力がHIGHかどうかを確認しますdigitalWrite(relayPin、HIGH); //リレーをオンにするif(pirState ==LOW){//シリアルをオンにしたばかりです.println( "モーションが検出されました!"); // 15秒の遅延delay(15000); //出力の変更のみを出力し、状態はpirState =HIGHではありません。 }} else {digitalWrite(relayPin、0); //リレーをオフにするif(pirState ==HIGH){// Serial.println( "モーションが終了しました!");をオフにしました//出力の変更のみを出力し、状態はpirState =LOWではありません。 }}}
main.py Python
import cv2.cv as cvfrom datetime import datetimeimport timeimport sysimport datetimecount =0class MotionDetector():def onChange(self、val):#callback when user change the ceil self.ceil =val def __init __(self、ceil =8 、doRecord =True、showWindows =True):self.writer =なしself.font =なしself.doRecord =doRecord#移動オブジェクトを記録するかどうかself.show =showWindows#2つのウィンドウを表示するかどうかself.frame =なしself.capture =cv.CaptureFromCAM(0)self.frame =cv.QueryFrame(self.capture)#doRecord:self.initRecorder()self.frame1gray =cv.CreateMat(self.frame。 height、self.frame.width、cv.CV_8U)#t-1の灰色のフレームcv.CvtColor(self.frame、self.frame1gray、cv.CV_RGB2GRAY)#しきい値の結果を保持しますself.res =cv.CreateMat(self .frame.height、self.frame.width、cv.CV_8U)self.frame2gray =cv.CreateMat(self.frame.height、s elf.frame.width、cv.CV_8U)#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.Que ryFrame(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 sel f.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 Falseif __name__=="__main__":detect =MotionDetector(doRecord=False) detect.run()
Dashboard FilesPHP
プレビューなし(ダウンロードのみ)。
Sanitation-Tunnel Android Source CodeJava
プレビューなし(ダウンロードのみ)。
Sanitation-Tunnel Android AppJava
Demo AppNo preview (download only).
Sanitation-Tunnel iOS Source CodeSwift
プレビューなし(ダウンロードのみ)。
Smart Disinfection and Sanitation Tunnel
https://github.com/yugn27/Smart-Disinfection-and-Sanitation-Tunnel カスタムパーツとエンクロージャー
smart_disinfection_and_sanitation_tunnel_prlFu8ZRXO.3mf 回路図
Circuit Diagram - fritzing file smart_disinfection_and_sanitation_tunnel_Zkb20Q5S2B.fzz製造プロセス