天天看點

用行空闆手搓一個桌面級蓋革計數器,實時探測核輻射強度!

用行空闆手搓一個桌面級蓋革計數器,實時探測核輻射強度!

視訊加載中...

介紹

目前輻射監測與我們息息相關,它不僅關系到我們的健康與安全,還隐藏着許多神秘和迷人的科學現象。核輻射是指來自放射性物質的粒子或電磁波的釋放。它分為三種類型:阿爾法輻射、貝塔輻射和伽馬射線。

這些輻射與我們日常生活息息相關,比如在醫學診斷、能源生産和食品輻照中的應用。然而,它們也帶來了一定的危險。了解這些輻射的特點和安全門檻值,能幫助我們更好地應對潛在的風險。

随手拿起身邊的行空闆,手搓了一個桌面版的蓋革計數器。簡單說這是一種專門探測電離輻射強度的記數儀器。

通常蓋革計數器由一個充氣密封管和一個資訊顯示屏構成,可以測得機關時間内的射線數。我将在下面詳細分享自制蓋革計數器的各個環節,以幫助我們日常監測輻射值和增加自定義功能。

用行空闆手搓一個桌面級蓋革計數器,實時探測核輻射強度!

硬體選型

現在我們一起來看看制作一個輻射監測器所需的硬體!

用行空闆手搓一個桌面級蓋革計數器,實時探測核輻射強度!

材料清單

  • 行空闆 X1
  • 蓋革計數器子產品 X1
  • 溫濕度傳感器 X1
  • U型公對母TypeC延長線 X1

接線圖

蓋革計數器子產品連接配接至行空闆pin23

DHT20溫濕度傳感器連接配接至行空闆IIC接口

用行空闆手搓一個桌面級蓋革計數器,實時探測核輻射強度!

3D列印外殼

3D列印外殼下載下傳連結: https://www.thingiverse.com/thing:6224720/files

用行空闆手搓一個桌面級蓋革計數器,實時探測核輻射強度!

蓋格計數器原理

如何測量輻射值呢?

這裡科普一下蓋革計數器的原理。

蓋革計數器是一種氣體放電探測器,内部充有易電離氣體,當輻射進入管中,會引起氣體電離,進而産生脈沖電流。這些脈沖信号被放大後就成為計數脈沖。我們隻需要統計機關時間内的脈沖個數,就可以直接計算出環境輻射量。相比其他探測器,蓋革計數管最大的優點是它輸出數字電信号,不需要複雜的模拟電路就可以實作輻射的精确計數。是以我們統計好每分鐘有多少個輻射粒子經過了氣體管,就可以得出目前環境的受輻射程度了。

用行空闆手搓一個桌面級蓋革計數器,實時探測核輻射強度!
用行空闆手搓一個桌面級蓋革計數器,實時探測核輻射強度!

如何計算輻射量?

這裡有三個關鍵的機關CPM、毫希弗(mSv/h),微希弗(uSv/h)。

CPM (Counts Per.Minute是種測量輻射水準的機關,為次/分鐘。它表示在一分内輻射值所接收到的輻射粒子擊中的次數。

而輻射水準可以用每小時受到輻射量水準的水準衡量:(Sv/h)、毫希弗(mSv/h)、微希弗(uSv/h)表示。

換算公式為 151CPM = 1uSv/h

1Sv/h = 1000mSv/h = 1000000uSh/h

如何評價和計量輻射程度?

《放射衛生防護基本标準》中提到,公衆中個人受到照射的年劑量當量限值是:全身均勻照射不超過5mSv;任何單個組織和或器官不超過50mSv;一生中每年的全身劑量當量限值應不高于1mSv。

室内環境中的核輻射劑量标準值為0.5uSV/h,根據公衆年輻射劑量限制5mSv/h進行計算,按照365*24小時的計算方法,劑量率不超過0.5uSv/h,在這個範圍内屬于正常範圍,一般室内環境的正常輻射劑量率在0.20uSv/h以下,大部分在0.13左右,但通常衛生間與廚房中存在的輻射劑量率較高。

程式編輯

用python程式設計計算微希弗(uSv/h)

計算機關時間間隔内(count)觸發多少次引腳中斷,判斷經過了多少個輻射粒子。這裡先設定為五秒計算一次(time_gap)。然後用60秒/5秒*經過的粒子數,計算出一分鐘經過的粒子數(cpm)。由于 151CPM = 1uSv/h,最終得出uSv/h的數值。

加載pinpong庫,用以python控制蓋格計數器

加載GUI庫,用以在顯示屏上顯示數字。

傳感器連接配接引腳p23,作為信号輸入。

import time
from pinpong.board import Board,Pin
 
Board("unihiker").begin()               #初始化,選擇闆型(uno、leonardo、xugu)和端口号,不輸入端口号則進行自動識别
from unihiker import GUI   #導入包
gui=GUI()  #執行個體化GUI類
btn = Pin(Pin.P23, Pin.IN)
           

設定變量和函數:

time_gap:輸入兩次計算微希弗(uSv/h)值的時間間隔

start_time:開始計數的時間

count:經過的粒子數

time_gap:兩次計算的時間間隔

uSvh:最終得出的輻射值

定義函數zero,确定開始計算時間并計數清零。

定義中斷函數,下降中斷時粒子計數+1。

定義get_cpm函數,計算出usvh的值。

time_gap = 0
start_time = 0
count = 0
time_gap = 5
uSvh = 0
 
def zero():
    global start_time,count
    start_time = time.time()
    count = 0
 
def btn_falling_handler(pin):#中斷事件回調函數
    global count
    count += 1
 
zero()
btn.irq(trigger=Pin.IRQ_FALLING, handler=btn_falling_handler) #設定中斷模式為下降沿觸發
 
def get_cpm():
    global uSvh
    if time.time() - start_time >= time_gap: 
        uSvh = round((count/151)*(60/time_gap),2)
        print("uSvh=",uSvh)
        zero()
           

顯示屏顯示

在150*90像素、黑色20号字顯示目前輻射值。

允許get_cpm函數,并更新顯示中的text。

dig = gui.draw_digit(x=150, y=90, text=uSvh, origin = "center",color="black",font_size=20,angle=90)#數位管字型顯示
 
while True:
    #start()
    time.sleep(1) #保持程式持續運作
    get_cpm()
    dig.config(text=uSvh)
           

全部代碼

用行空闆手搓一個桌面級蓋革計數器,實時探測核輻射強度!
import time
from pinpong.board import Board,Pin
 
Board("unihiker").begin()               #初始化,選擇闆型(uno、leonardo、xugu)和端口号,不輸入端口号則進行自動識别
from unihiker import GUI   #導入包
gui=GUI()  #執行個體化GUI類
btn = Pin(Pin.P23, Pin.IN)
 
time_gap = 0
start_time = 0
count = 0
time_gap = 5
uSvh = 0
 
def zero():
    global start_time,count
    start_time = time.time()
    count = 0
 
def btn_falling_handler(pin):#中斷事件回調函數
    global count
    count += 1
 
zero()
btn.irq(trigger=Pin.IRQ_FALLING, handler=btn_falling_handler) #設定中斷模式為下降沿觸發
 
def get_cpm():
    global uSvh
    if time.time() - start_time >= time_gap: 
        uSvh = round((count/151)*(60/time_gap),2)
        print("uSvh=",uSvh)
        zero()
 
dig = gui.draw_digit(x=150, y=90, text=uSvh, origin = "center",color="black",font_size=20,angle=90)#數位管字型顯示
 
while True:
    #start()
    time.sleep(1) #保持程式持續運作
    get_cpm()
    dig.config(text=uSvh)
           

顯示優化

現在輻射值顯示出來了,但畫面略顯單調。此時我們可以嘗試增加溫濕度傳感器,同時顯示溫濕度、實時的年月日資訊、和輻射值變化的折線圖。當輻射值超過0.5uSvh的時候,行空闆發出蜂鳴聲并且數值顯示紅色。

  • 溫濕度傳感器:DHT20
  • 加載溫濕度傳感器的庫:from pinpong.libs.dfrobot_dht20 import DHT20
  • 數字橫向顯示,在這段代碼後面加上‘angle=90’。tem1 = gui.draw_text(x=55, y=263, text="Temperature :", origin = "center",color="white",font_size=8,angle=90)
  • 繪制線段的函數:line1=gui.draw_line(x0=(numberMap((uSvh_list[0]), 0, 1.1, 239, 200)),y0=320,x1=(numberMap((uSvh_list[1]), 0, 1.1, 239, 200)),y1=288,width=2,color="#acacac")
  • 年月日和時間的顯示: DigitalTime.config(text=time.strftime("%Y/%m/%d %H:%M"))
  • 折線圖始終顯示最新的10個資料的變化:def numberMap(x, in_min, in_max, out_min, out_max): return (x - in_min) * (out_max - out_min) / (in_max - in_min) + out_min
import time
from pinpong.board import Board,Pin
from pinpong.libs.dfrobot_dht20 import DHT20
from pinpong.extension.unihiker import *
 
 
Board("unihiker").begin()               #初始化,選擇闆型(uno、leonardo、xugu)和端口号,不輸入端口号則進行自動識别
from unihiker import GUI   #導入包
gui=GUI()  #執行個體化GUI類
 
btn = Pin(Pin.P23, Pin.IN)
p_dht20 = DHT20()
#global num_pulse1
 
time_gap = 0
start_time = 0
count = 0
time_gap = 5
uSvh = 0
 
 
def zero():
    global start_time,count
    start_time = time.time()
    count = 0
#    print('start',start_time)
 
 
def btn_falling_handler(pin):#中斷事件回調函數
    global count
    count += 1
    # print("pulse = ", count)
 
zero()
 
btn.irq(trigger=Pin.IRQ_FALLING, handler=btn_falling_handler) #設定中斷模式為下降沿觸發
 
 
def get_cpm():
    # print("time:",time.time())
    global uSvh
    global dht1
    global p_dht20
    if time.time() - start_time >= time_gap: 
        print("-------------------")
        print("count=",count)
        uSvh = round((count/151)*(60/time_gap),2)
        print("uSvh=",uSvh)
        zero()
 
def numberMap(x, in_min, in_max, out_min, out_max):
  return (x - in_min) * (out_max - out_min) / (in_max - in_min) + out_min
 
uSvh_list = [0,0,0,0,0,0,0,0,0,0,0]
 
bg = gui.fill_rect(x=0, y=0, w=240, h=320,  width=3, color=(0, 0, 0),onclick=lambda: print("rect clicked"))
tem1 = gui.draw_text(x=55, y=263, text="Temperature :", origin = "center",color="white",font_size=8,angle=90)#數位管字型顯示
tem2 = gui.draw_digit(x=95,y=240,text=(int(float(p_dht20.temp_c()))),origin = "center",color="white",font_size=33,angle=90)
tem3 = gui.draw_digit(x=105, y=190, text="°C", origin = "center",color="white",font_size=10,angle=90)#數位管字型顯示
humi1 = gui.draw_text(x=57, y=140, text="Humidity :", origin = "center",color="white",font_size=8,angle=90)#數位管字型顯示
humi2 = gui.draw_digit(x=95,y=100,text=(int(float(p_dht20.humidity()))),origin = "center",color="white",font_size=33,angle=90)
humi3 = gui.draw_digit(x=105, y=45, text="%rh", origin = "center",color="white",font_size=10,angle=90)#數位管字型顯示
 
u1 = gui.draw_text(x=143, y=270, text="Radiation :", origin = "center",color="white",font_size=8,angle=90)#數位管字型顯示
u2 = gui.draw_digit(x=175, y=150, text=uSvh, origin = "center",color="white",font_size=45,angle=90)#數位管字型顯示
u3 = gui.draw_digit(x=190, y=45, text="uSvh", origin = "center",color="white",font_size=12,angle=90)#數位管字型顯示
 
DigitalTime=gui.draw_digit(text=time.strftime("%Y/%m/%d          %H:%M"),x=10,y=310,font_size=15, color="white",angle=90)
 
if (len(uSvh_list) >= 12):
    uSvh_list.pop((len(uSvh_list) - 1))
print(uSvh_list)
line1=gui.draw_line(x0=(numberMap((uSvh_list[0]), 0, 1.1, 239, 200)),y0=320,x1=(numberMap((uSvh_list[1]), 0, 1.1, 239, 200)),y1=288,width=2,color="#acacac")
line2=gui.draw_line(x0=(numberMap((uSvh_list[1]), 0, 1.1, 239, 200)),y0=288,x1=(numberMap((uSvh_list[2]), 0, 1.1, 239, 200)),y1=256,width=2,color="#acacac")
line3=gui.draw_line(x0=(numberMap((uSvh_list[2]), 0, 1.1, 239, 200)),y0=256,x1=(numberMap((uSvh_list[3]), 0, 1.1, 239, 200)),y1=224,width=2,color="#acacac")
line4=gui.draw_line(x0=(numberMap((uSvh_list[3]), 0, 1.1, 239, 200)),y0=224,x1=(numberMap((uSvh_list[4]), 0, 1.1, 239, 200)),y1=192,width=2,color="#acacac")
line5=gui.draw_line(x0=(numberMap((uSvh_list[4]), 0, 1.1, 239, 200)),y0=192,x1=(numberMap((uSvh_list[5]), 0, 1.1, 239, 200)),y1=160,width=2,color="#acacac")
line6=gui.draw_line(x0=(numberMap((uSvh_list[5]), 0, 1.1, 239, 200)),y0=160,x1=(numberMap((uSvh_list[6]), 0, 1.1, 239, 200)),y1=128,width=2,color="#acacac")
line7=gui.draw_line(x0=(numberMap((uSvh_list[6]), 0, 1.1, 239, 200)),y0=128,x1=(numberMap((uSvh_list[7]), 0, 1.1, 239, 200)),y1=96,width=2,color="#acacac")
line8=gui.draw_line(x0=(numberMap((uSvh_list[7]), 0, 1.1, 239, 200)),y0=96,x1=(numberMap((uSvh_list[8]), 0, 1.1, 239, 200)),y1=64,width=2,color="#acacac")
line9=gui.draw_line(x0=(numberMap((uSvh_list[8]), 0, 1.1, 239, 200)),y0=64,x1=(numberMap((uSvh_list[9]), 0, 1.1, 239, 200)),y1=32,width=2,color="#acacac")
line10=gui.draw_line(x0=(numberMap((uSvh_list[9]), 0, 1.1, 239, 200)),y0=32,x1=(numberMap((uSvh_list[10]), 0, 1.1, 239, 200)),y1=0,width=2,color="#acacac")
 
 
while True:
    #start()
    time.sleep(1) #保持程式持續運作
    get_cpm()
    # tem1.config(text="溫度:")
    tem2.config(text=(int(float(p_dht20.temp_c()))))
    # humi1.config(text="濕度:")
    humi2.config(text=(int(float(p_dht20.humidity()))))
    # u1.config(text="輻射量:")
    u2.config(text=uSvh,color="white")
    DigitalTime.config(text=time.strftime("%Y/%m/%d          %H:%M"))
 
    print(uSvh_list)
    uSvh_list.insert(0,uSvh)
    line1.config(x0=(numberMap((uSvh_list[0]), 0, 1.1, 239, 200)),y0=320,x1=(numberMap((uSvh_list[1]), 0, 1.1, 239, 200)),y1=288)
    line2.config(x0=(numberMap((uSvh_list[1]), 0, 1.1, 239, 200)),y0=288,x1=(numberMap((uSvh_list[2]), 0, 1.1, 239, 200)),y1=256)
    line3.config(x0=(numberMap((uSvh_list[2]), 0, 1.1, 239, 200)),y0=256,x1=(numberMap((uSvh_list[3]), 0, 1.1, 239, 200)),y1=224)
    line4.config(x0=(numberMap((uSvh_list[3]), 0, 1.1, 239, 200)),y0=224,x1=(numberMap((uSvh_list[4]), 0, 1.1, 239, 200)),y1=192)
    line5.config(x0=(numberMap((uSvh_list[4]), 0, 1.1, 239, 200)),y0=192,x1=(numberMap((uSvh_list[5]), 0, 1.1, 239, 200)),y1=160)
    line6.config(x0=(numberMap((uSvh_list[5]), 0, 1.1, 239, 200)),y0=160,x1=(numberMap((uSvh_list[6]), 0, 1.1, 239, 200)),y1=128)
    line7.config(x0=(numberMap((uSvh_list[6]), 0, 1.1, 239, 200)),y0=128,x1=(numberMap((uSvh_list[7]), 0, 1.1, 239, 200)),y1=96)
    line8.config(x0=(numberMap((uSvh_list[7]), 0, 1.1, 239, 200)),y0=96,x1=(numberMap((uSvh_list[8]), 0, 1.1, 239, 200)),y1=64)
    line9.config(x0=(numberMap((uSvh_list[8]), 0, 1.1, 239, 200)),y0=64,x1=(numberMap((uSvh_list[9]), 0, 1.1, 239, 200)),y1=32)
    line10.config(x0=(numberMap((uSvh_list[9]), 0, 1.1, 239, 200)),y0=32,x1=(numberMap((uSvh_list[10]), 0, 1.1, 239, 200)),y1=0)
 
    i = uSvh
    if (i > 0.5):
        u2.config(text=uSvh,color="red")
        buzzer.pitch(466,8)
        i = 0
 
    time.sleep(1)
           

使用行空闆DIY自制的桌面蓋革計數器,可以非常便捷地實時監測環境中的輻射水準。它具有制作簡單、使用友善、成本低廉等優點,通過簡單的脈沖統計就可以計算出輻射劑量率,幫助我們實時了解周圍的輻射情況。同時,項目中使用的行空闆不僅具備了可以觸摸的螢幕,還可以與其他硬體傳感器連接配接。直接使用python程式設計也極大的增加了創造的靈活度。與一般商業檢測裝置相比,這種自制裝置更加靈活和可定制化,我們可以添加報警功能、資料記錄功能等,讓輻射檢測更智能化。總之,在核污染日漸被熟知的當下,制作一台桌面版蓋革計數器,讓輻射監測觸手可及,既可提高輻射安全意識,也是一件有意義的創造。

蓋革在手,輻射逃走!

原文首發于:https://makelog.dfrobot.com.cn/article-313483.html

轉載請注明來源資訊