一、介紹
?? 磁簧開關(guān)(Reed Switch)也稱之為干簧管筹吐,它是一個通過所施加的磁場操作的電開關(guān)猛频∈ū溃基本型式是將兩片磁簧片密封在玻璃管內(nèi)蛛勉,兩片雖重疊,但中間間隔有一小空隙睦柴。當(dāng)外來磁場時將使兩片磁簧片接觸诽凌,進(jìn)而導(dǎo)通。 一旦磁體被拉到遠(yuǎn)離開關(guān)坦敌,磁簧開關(guān)將返回到其原來的位置侣诵。可以用來計(jì)數(shù)或限制位置狱窘。
二杜顺、組件
★Raspberry Pi 3主板*1
★樹莓派電源*1
★40P軟排線*1
★干簧管傳感器模塊*1
★雙色LED模塊*1
★面包板*1
★跳線若干
三、實(shí)驗(yàn)原理
??磁簧開關(guān)的工作原理非常簡單蘸炸,兩片端點(diǎn)處重疊的可磁化的簧片(通常由鐵和鎳這兩種金屬所組成的)密封于一玻璃管中哑舒,兩簧片呈交迭狀且間隔有一小段空隙(僅約幾個[微米]),這兩片簧片上的觸點(diǎn)上鍍有層很硬的金屬幻馁,通常都是銠和釕洗鸵,這層硬金屬大大提升了切換次數(shù)及產(chǎn)品壽命。玻璃管中裝填有高純度的惰性氣體(如氮?dú)?仗嗦,部份干簧開關(guān)為了提升其高壓性能膘滨,更會把內(nèi)部做成真空狀態(tài)。
??簧片的作用相當(dāng)與一個磁通導(dǎo)體稀拐。在尚未操作時火邓,兩片簧片并未接觸;在通過[永久磁鐵]或電磁線圈產(chǎn)生的磁場時德撬,外加的磁場使兩片簧片端點(diǎn)位置附近產(chǎn)生不同的極性, 當(dāng)[磁力]超過簧片本身的彈力時铲咨,這兩片簧片會吸合導(dǎo)通電路;當(dāng)磁場減弱或消失后,干簧片由于本身的彈性而釋放蜓洪,觸面就會分開從而打開電路纤勒。
??在此實(shí)驗(yàn)中,將雙色LED模塊連接到樹莓派以指示開關(guān)的斷開閉合隆檀。敲擊或敲擊振動傳感器時摇天,它將打開,雙色led將閃爍綠色恐仑,再次敲擊它將變?yōu)榧t色泉坐,每一次敲擊后會在兩種顏色之間切換。
四裳仆、實(shí)驗(yàn)步驟
??第1步:連接電路腕让,該實(shí)驗(yàn)與實(shí)驗(yàn)6(輕觸開關(guān)按鍵實(shí)驗(yàn))相同。這里激光模塊的實(shí)物與模塊原理圖的端口名稱不一致,我們按照實(shí)物的端口名稱來連接拣技。
樹莓派 | T型轉(zhuǎn)接板 | 干簧管傳感器 |
---|---|---|
GPIO 0(序號11) | GPIO 17 | SIG(DO) |
5V | 5V | VCC |
GND | GND | GND |
樹莓派 | T型轉(zhuǎn)接板 | 雙色LED |
---|---|---|
GPIO 1(序號12) | GPIO 18 | R(紅色端口) |
GND | GND | GND |
GPIO 2(序號13) | GPIO 27 | G(綠色端口) |
??第2步:這次編程有兩個函數(shù)要注意,是關(guān)于輸入的高級應(yīng)用独郎。
??有多種方式將GPIO的輸入導(dǎo)入到程序中液南,polling( 輪詢 )式 和 interrupt( 中斷 )式( edge detection 邊緣檢測 )壳猜,“輪詢”式如果程序在錯誤的時間讀取值,可能會錯過輸入滑凉。我們這里采用中斷式统扳。
??如果您沒有將輸入引腳連接到任何東西,它將“浮動”畅姊。換句話說咒钟,讀取的值是未定義的,因?yàn)樗鼪]有連接到任何東西若未,直到你按下按鈕或開關(guān)朱嘴。它可能會由于接收電源干擾而改變很大的值。
??為了解決這個問題粗合,我們使用一個向上拉或向下拉電阻器萍嬉。這樣,就可以設(shè)置輸入的默認(rèn)值隙疚∪雷罚可以使用硬件或者軟件實(shí)現(xiàn)上下拉電阻。在硬件方式中供屉,常常在輸入通道與3.3V(上拉)或0V(下拉)之間使用10K電阻行冰。GPIO模塊允許您在編程中這樣配置:
GPIO.setup(channel, GPIO.IN, pull_up_down=GPIO.PUD_UP)
# or
GPIO.setup(channel, GPIO.IN, pull_up_down=GPIO.PUD_DOWN)
??我們很多時候并不關(guān)心電平值, 而關(guān)心電平從低到高,或從高到低的變化(如編碼器測速/按鍵按下彈開等), 為避免主程序忙于其它事情錯過引腳的電平改變, 有兩種方式:
??wait_for_edge() 函數(shù)
?? event_detected() 函數(shù)
?? wait_for_edge()函數(shù)是為了阻止程序的執(zhí)行伶丐,直到檢測到邊緣為止悼做。換句話說,等待按鈕按下的示例可以改寫成:
GPIO.wait_for_edge(channel, GPIO.RISING)
?? 注意檢測的邊緣參數(shù)有 GPIO.RISING哗魂, GPIO.FALLING 肛走, GPIO.BOTH (上升沿, 下降沿 或 升降沿), 這樣用幾乎不占用CPU啡彬,如果你只希望在確定的時間段內(nèi)查詢羹与,可以使用 timeout 參數(shù):
# wait for up to 5 seconds for a rising edge (timeout is in milliseconds)
channel = GPIO.wait_for_edge(channel, GPIO_RISING, timeout=5000)
if channel is None:
print('Timeout occurred')
else:
print('Edge detected on channel', channel)
??event_detected()函數(shù)被設(shè)計(jì)用來與其他事物一起在循環(huán)中使用, 不同于polling輪詢庶灿, 它不會在CPU忙于處理其他事物時錯過輸入狀態(tài)的變化。 這使得使用Pygame 或 PyQt 時非常有用吃衅,因?yàn)槠渲杏幸粋€主循環(huán)監(jiān)聽和及時響應(yīng)GUI事件的基礎(chǔ)往踢。
??只要檢測到指定參數(shù)的邊緣事件(上升沿, 下降沿 或 升降沿)發(fā)生時,調(diào)用GPIO.event_detected(channel)的值就為"ture"(真)徘层。
#Note that you can detect events for GPIO.RISING, GPIO.FALLING or GPIO.BOTH.
GPIO.add_event_detect(channel, GPIO.RISING) # add rising edge detection on a channel
do_something()
if GPIO.event_detected(channel):
print('Button pressed')
??不過需要自己新建一個線程去循環(huán)檢測event_detected()的值峻呕,還算是比較麻煩的利职。
??可采用另一種辦法輕松檢測狀態(tài),這種方式是直接傳入一個回調(diào)函數(shù):GPIO通過在add_event_detect()函數(shù)中添加callback參數(shù)瘦癌,RPI.GPIO為回調(diào)函數(shù)運(yùn)行第二個線程猪贪。這意味著回調(diào)函數(shù)可以與主程序同時運(yùn)行,以立即響應(yīng)邊緣讯私。
??For example:
def my_callback(channel):
print('This is a edge event callback function!')
print('Edge detected on channel %s'%channel)
print('This is run in a different thread to your main program')
GPIO.add_event_detect(channel, GPIO.RISING, callback=my_callback)
# 這里添加了回調(diào)函數(shù)callback這個參數(shù)热押,就不需要GPIO.event_detected(channel)函數(shù)了
??如果你想要不止一個回調(diào)函數(shù):
def my_callback_one(channel):
print('Callback one')
def my_callback_two(channel):
print('Callback two')
GPIO.add_event_detect(channel, GPIO.RISING)
GPIO.add_event_callback(channel, my_callback_one)
GPIO.add_event_callback(channel, my_callback_two)
??請注意,在這種情況下斤寇,回調(diào)函數(shù)是按順序運(yùn)行的桶癣,而不是并發(fā)的。這是因?yàn)橹挥幸粋€線程用于回調(diào)娘锁,其中每個回調(diào)都按照它們被定義的順序運(yùn)行牙寞。
??由于存在開關(guān)抖動(用示波器可以看到),每次按下開關(guān)會調(diào)用多次回調(diào)函數(shù)莫秆,這不是我們希望的间雀,有兩種方式處理開關(guān)抖動:
??①在開關(guān)兩個引腳之間添加一個0.1uF的電容
??②軟件消抖
??③二者結(jié)合使用
??使用軟件消抖時, 給回調(diào)函數(shù)添加一個彈跳時間的參數(shù)( bouncetime= ), 彈跳時間(參照單片機(jī)可以為10~20ms)在ms級別, 下面的程序用200ms來消抖:
# add rising edge detection on a channel, ignoring further edges for 200ms for switch bounce handling
GPIO.add_event_detect(channel, GPIO.RISING, callback=my_callback, bouncetime=200)
??由于某些原因, 你的程序可能不希望用邊緣檢測了镊屎,可以停止它們:
GPIO.remove_event_detect(channel)
??第3步:正式編程雷蹂。定義針腳參數(shù)和初始化設(shè)置函數(shù)setup(),其中就用到了上面講解的GPIO輸入高級應(yīng)用杯道,添加邊緣事件檢測函數(shù)GPIO.add_event_detect()匪煌。
#!/usr/bin/env python
import RPi.GPIO as GPIO
ReedPin = 11
Rpin = 12
Gpin = 13
def setup():
GPIO.setmode(GPIO.BOARD) # Numbers GPIOs by physical location
GPIO.setup(Gpin, GPIO.OUT) # Set Green Led Pin mode to output
GPIO.setup(Rpin, GPIO.OUT) # Set Red Led Pin mode to output
GPIO.setup(ReedPin, GPIO.IN, pull_up_down=GPIO.PUD_UP) # Set BtnPin's mode is input, and pull up to high level(3.3V)
GPIO.add_event_detect(ReedPin, GPIO.BOTH, callback=detect, bouncetime=200)
??第4步:定義Led(x)函數(shù),控制雙色LED燈閃爍党巾。定義Print(x)萎庭,打印按鍵是否切換開關(guān)的提示消息。檢測到磁鐵時齿拂,傳感器輸出低電平驳规,干簧管簧片拉在一起,電路聯(lián)通署海,紅燈亮吗购;拿開磁鐵時,傳感器輸出高電平砸狞,干簧管簧片分開捻勉,電路斷開,綠燈亮刀森。
def Led(x): #控制雙色LED燈閃爍的函數(shù)
if x == 0: #傳感器輸出低電平踱启,干簧管簧片拉在一起,電路聯(lián)通,紅燈亮
GPIO.output(Rpin, 1)
GPIO.output(Gpin, 0)
if x == 1: #傳感器輸出高電平埠偿,干簧管簧片分開透罢,電路斷開,綠燈亮
GPIO.output(Rpin, 0)
GPIO.output(Gpin, 1)
def Print(x): #打印檢測到磁性物質(zhì)
if x == 0:
print ' ***********************************'
print ' * Detected Magnetic Material! *'
print ' ***********************************'
??第5步:檢測到磁鐵時(或者拿開磁鐵時)冠蒋,邊緣事件檢測函數(shù)都會回調(diào)detect(chn)函數(shù)羽圃,產(chǎn)生低電平信號(或者高電平信號),GPIO.input(ReedPin)的值為0(或1)抖剿,LED燈會呈紅(或綠)顏色朽寞。
def detect(chn):
Led(GPIO.input(ReedPin)) #控制雙色LED燈閃爍的函數(shù)
Print(GPIO.input(ReedPin)) #打印檢測到磁性物質(zhì)
print GPIO.input(ReedPin) #驗(yàn)證GPIO.input(ReedPin)的值
def loop():
while True:
pass
??第6步:創(chuàng)建destroy()函數(shù),清除LED狀態(tài)牙躺。創(chuàng)建程序入口愁憔,并包含異常處理。
def destroy():
GPIO.output(Gpin, GPIO.LOW) # Green led off
GPIO.output(Rpin, GPIO.LOW) # Red led off
GPIO.cleanup() # Release resource
if __name__ == '__main__': # Program start from here
setup()
try:
loop()
except KeyboardInterrupt: # When 'Ctrl+C' is pressed, the child program destroy() will be executed.
destroy()