敢碰就報警的Arduino Yún系統
如果你想做一個報警系統,目的恐怕再明確不過了------你不想讓孩子爬上櫥柜或是冰箱偷東西吃,也不想其他人偷開你的鎖柜。當然啦,可能你會想給偷吃食物的寵物拍張照片。或者,你想學學美劇《辦公室》里Dwight?Schrute所扮演的角色,看看是誰把同事的工作材料換成了果凍。那么問題來了,你該怎么做呢?
是的,你可以在櫥柜/冰箱/鎖柜里放上一個設備,一旦它監測到有動靜,就會拍一張照片然后發送到你的電子郵件里。還有如果你會IFTTT(讓互聯網為你服務)的話,甚至可以自動把那些“小偷們”的照片發到社交媒體上,讓全世界看看他們的臉。
首先,讓我們先來欣賞一下小哥浮夸的演技:
這個報警系統項目,由一個運動傳感器(PIR),一個攝像頭,以及一個支持無線Wi-Fi連接設備組成。筆者選擇了 Arduino ?Yún,因為它非常易于使用,還能輕松配置無線Wi-Fi,而且如果你想換成RaspberryPi,也很容易。當然啦,如果你使用RaspberryPi的話,Wi-Fi配置可能會略微麻煩一些,因為它必須要連接到一臺計算機上才能進行配置操作,而使用Arduino?Yún就相對輕松多了,任何人都可以在上面直接配置。這個報警系統項目其實非常簡單,即便你沒有什么焊接/電氣方面的技巧,也能在幾分鐘時間里輕松完成組裝。廢話不多說,趕緊來看看怎么做吧。
第一步?Arduino基本配置
首先,你需要配置自己的Arduino?Yún網絡設置,如果你按照教程一步步操作,其實非常簡單。?點擊查看教程.
完成配置之后,你需要測試Arduino的連接狀況。打開瀏覽器,輸入http://arduino.local,然后即能看到Arduino網頁界面了。
如果一切操作正常,打開SSH會話。
$?sshroot@arduino.local
默認密碼是:“arduino”。
然后,讓我們來安裝一些有用的軟件包
$opkg?update
$opkg?install?openssh-sftp-server
那么,為什么要安裝“openssh-sftp-server”呢?因為這個軟件包可以讓你從Arduino上面輕松上傳或下載文件。現在,你可以使用一個通用的SFTP客戶端,比如filezilla,transmit,或是cyberduck等等,這樣就不用輸入麻煩的SCP命令來進行文件傳輸了。
然后,為了兼容Python,我們還需要安裝一個SSL支持包(感謝sbkirby!)。因為在默認軟件包里,并沒有包含這個軟件支持包。
$opkg?update
$opkg?install?python-openssl
筆者墻裂推薦你可以在Arduino?Yún上插一個SD卡(如果你有一個的話),Arduino?Yún設備會自動分配文件路徑,地址是mnt/sda1。
然后,我們要在Arduino?Yún上面安裝USB攝像頭和USB聲卡。
第二步? 安裝并測試USB攝像頭
通過opkg套件管理系統,已經有支持Linino的UVC軟件包了,因此安裝攝像頭可以說是非常簡單的一個步驟。是需要通過ssh連接到Yún上面,然后輸入:
$?opkg?update
$?opkg?install?kmod-video-uvc
就可以了。
不過我們還需要一個可以拍照片的軟件,筆者使用過一款容量極小,但又非常便于使用的拍照軟件fswebcam,按照如下命令,安裝即可。
$?opkg?install?fswebcam
第三步? 拍攝你的第一張照片
首先要確保你使用了SD卡作為存儲,否則Arduino內存會很快就被耗盡。好了,如果你正在使用SD存儲卡的話,你應該已經能夠看到它的安裝路徑地址了/mnt/sda1.如果你還沒有使用,那么請將FAT32格式的SD卡插入到設備的SD卡插槽里面,并重啟你的Arduino設備。
現在,請把攝像頭插進設備的USB端口,然后輸入:
$?cd?/mnt/sda1
$?fswebcam?test.png
如果一切正常的話,你現在就能拍攝自己的第一張照片啦!注意看看你的SD卡里的內容哦,:)
這意味著,現在我們可以通過Yún’s?Bridge庫,在自己的Arduino設備里面拍照片,按照下面這種操作方式就能實現:
Process.runShellCommand("fswebcam?/mnt/sda1/test.png");
第四步? 安裝聲卡
在Yún上打開一個ssh會話,然后輸入:
$opkg?install?kmod-usb-audio
$opkg?install?madplay
完成安裝之后,現在Arduino?Yún設備就有了聲卡支持了。筆者只嘗試了下MP3格式的音樂播放,還沒有自己錄制一些音頻,但是很快就會去嘗試下!
如果想要測試一下聲卡效果,其實也非常簡單,你只需在SD卡里復制一個MP3音頻文件,然后輸入:
$cd?/mnt/sda1
$madplay?yoursound.mp3??
這意味著現在我們可以通過Yún’s?Bridge庫,在Arduino設備里面播放聲音了,按照下面這種操作方式就能實現: ?
Process.runShellCommand("madplay?/mnt/sda1/test.mp3");
第五步? 電子郵件腳本
現在,我們的監控設備可以拍照片并且支持播放聲音….但是我們還想要更多功能!我們想讓這款設備能通過電子郵件發送文件。
所以,我們該怎么做呢?答案其實非常簡單….一個python腳本就能搞定!Arduino?Yún整合了Temboo庫,筆者想讓這個監控系統更加具有兼容性,因此我們會使用一個非常簡單的python腳本編碼圖像文件,并通過電子郵件發送出去。
筆者選擇的電子郵箱是 Gmail ,但是這個代碼腳本其實可以選擇任何支持SMTP服務器的電子郵箱。
你可以創建一個新文件,稱之為“sendemail.py”,然后把下面這段代碼復制進去,
#?coding=utf-8
#?Copyright?(C)?2014??Stefano?Guglielmetti
#?This?program?is?free?software:?you?can?redistribute?it?and/or?modify
#?it?under?the?terms?of?the?GNU?General?Public?License?as?published?by
#?the?Free?Software?Foundation,?either?version?3?of?the?License,?or
#?(at?your?option)?any?later?version.
#?This?program?is?distributed?in?the?hope?that?it?will?be?useful,
#?but?WITHOUT?ANY?WARRANTY;?without?even?the?implied?warranty?of
#?MERCHANTABILITY?or?FITNESS?FOR?A?PARTICULAR?PURPOSE.?See?the
#?GNU?General?Public?License?for?more?details.
#?You?should?have?received?a?copy?of?the?GNU?General?Public?License
#?along?with?this?program.?If?not,?see?<http://www.gnu.org/licenses/>.
import?smtplib,?os,?sys
from?email.MIMEMultipart?import?MIMEMultipart
from?email.MIMEBase?import?MIMEBase
from?email.MIMEText?import?MIMEText
from?email.Utils?import?COMMASPACE,?formatdate
from?email?import?Encoders
#From?address,?to?address,?subject?and?message?body
from_address????=?'FROM_ADDRESS@EMAIL.COM'
to_address??????=?['YOUR_ADDRESS@EMAIL.COM']
email_subject???=?'Alert!!!?Zombies!!!?Ahead!!!'
email_body??????=?'A?non?dead?intruder?has?been?detected?and?needs?to?be?eliminated!'
#?Credentials?(if?needed)
username?=?'EMAIL_LOGIN'
password?=?'EMAIL_PASSWORD'
#?The?actual?mail?send
server?=?'smtp.gmail.com:587'
def?send_mail(send_from,?send_to,?subject,?text,?files=[],?server="localhost"):
????assert?type(send_to)==list
????assert?type(files)==list
????msg?=?MIMEMultipart()
????msg['From']?=?send_from
????msg['To']?=?COMMASPACE.join(send_to)
????msg['Date']?=?formatdate(localtime=True)
????msg['Subject']?=?subject
????msg.attach(?MIMEText(text)?)
????for?f?in?files:
????????part?=?MIMEBase('application',?"octet-stream")
????????part.set_payload(?open(f,"rb").read()?)
????????Encoders.encode_base64(part)
????????part.add_header('Content-Disposition',?'attachment;?filename="%s"'?%?os.path.basename(f))
????????msg.attach(part)
????smtp?=?smtplib.SMTP(server)
????smtp.starttls()
????smtp.login(username,password)
????smtp.sendmail(send_from,?send_to,?msg.as_string())
????smtp.close()
send_mail(from_address,?to_address,?email_subject,?email_body,?[sys.argv[1]],?server)?#the?first?command?line?argument?will?be?used?as?the?image?file?name
現在,你需要把相關電子郵件設置做下改動,如下
#From?address,?to?address,?subject?and?message?body
from_address????=?'FROM_ADDRESS@EMAIL.COM'
to_address??????=?['YOUR_ADDRESS@EMAIL.COM']
email_subject???=?'Alert!!!?Zombies!!!?Ahead!!!'
email_body??????=?'An?undead?intruder?has?been?detected?and?needs?to?be?eliminated!' ?
#?Credentials?(if?needed)
username?=?'EMAIL_LOGIN'
password?=?'EMAIL_PASSWORD'
#?The?actual?mail?send
server?=?'smtp.gmail.com:587'
接下來,你可以通過SFTP(或是SCP,如果你喜歡的話)把這段腳本文件上傳到Arduino?Yún的SD卡里,然后再次打開SSH會話,輸入下面這段命令:
$cd?/mnt/sda1
$python?sendemail.py?test.png
幾秒鐘之后,你就會收到一封電子郵件,附件就是Arduino?Yún拍攝的照片,是不是很神奇!
第六步? 讓我們搭設電路板!
別擔心,這一個步驟其實也是非常簡單的。你根本用不著焊接什么材料,所有部件都能靠組裝完成。筆者使用了這款PIR傳感器,是因為它即可靠,又方便使用。你可以參照下圖來進行相關操作:
我們已經連上了這個PIR傳感器。如果監控系統設備發現了一些動作,上面的LED燈就會打開。
第七步? 現在是時候加上Arduino?Sketch了
在Arduino?IDE上復制下面這段代碼,然后上傳到你的Yún上:
*?
?*?Switches?a?LED,?takes?a?picture?and?sends?it?via?email
?*?according?to?the?state?of?the?sensors?output?pin.
?*?Determines?the?beginning?and?end?of?continuous?motion?sequences.
?*
?*?@author:?Stefano?Guglielmetti?/?stefano?(at)?mikamai?(dot)?com?/?http://jeko.net
?*?@date:???feb?5,?2014??
?*
?*?based?on?the?example?by?Kristian?Gohlke?/?krigoo?(_)?gmail?(_)?com?/?http://krx.at
?*?http://playground.arduino.cc/Code/PIRsense
?*
?*?stefano?guglielmetti?(cleft)?2014?
?*
?*?released?under?a?creative?commons?"Attribution-NonCommercial-ShareAlike?2.0"?license
?*?http://creativecommons.org/licenses/by-nc-sa/2.0/de/
?*
?*
?*?The?Parallax?PIR?Sensor?is?an?easy?to?use?digital?infrared?motion?sensor?module.?
?*?(http://www.parallax.com/detail.asp?product_id=555-28027)
?*
?*?The?sensor's?output?pin?goes?to?HIGH?if?motion?is?present.
?*?However,?even?if?motion?is?present?it?goes?to?LOW?from?time?to?time,?
?*?which?might?give?the?impression?no?motion?is?present.?
?*?This?program?deals?with?this?issue?by?ignoring?LOW-phases?shorter?than?a?given?time,?
?*?assuming?continuous?motion?is?present?during?these?phases.
?*??
?*/
#include?<Bridge.h>
/////////////////////////////
//VARS
//the?time?we?give?the?sensor?to?calibrate?(10-60?secs?according?to?the?datasheet)
int?calibrationTime?=?10; ? ? ? ?
//the?time?when?the?sensor?outputs?a?low?impulse
long?unsigned?int?lowIn; ? ? ? ??
//the?amount?of?milliseconds?the?sensor?has?to?be?low?
//before?we?assume?all?motion?has?stopped
long?unsigned?int?pause?=?5000; ?
boolean?lockLow?=?true;
boolean?takeLowTime; ?
int?pirPin?=?6;????//the?digital?pin?connected?to?the?PIR?sensor's?output
int?ledPin?=?13;
Process?p;
String?imageName;
/////////////////////////////
//SETUP
void?setup(){
??Bridge.begin();
??Serial.begin(9600);
??pinMode(pirPin,?INPUT);
??pinMode(ledPin,?OUTPUT);
??digitalWrite(pirPin,?LOW);
??//give?the?sensor?some?time?to?calibrate
??Serial.print("calibrating?sensor?");
??for(int?i?=?0;?i?<?calibrationTime;?i++){
????Serial.print(".");
????delay(1000);
??}
??Serial.println("?done");
??Serial.println("SENSOR?ACTIVE");
??delay(50);
}
?
////////////////////////////
//LOOP
void?loop(){
??if(digitalRead(pirPin)?==?HIGH){
????digitalWrite(ledPin,?HIGH);???//the?led?visualizes?the?sensors?output?pin?state
????if(lockLow){??
??????//makes?sure?we?wait?for?a?transition?to?LOW?before?any?further?output?is?made:
??????lockLow?=?false;????????????
??????Serial.println("---");
??????Serial.print("motion?detected?at?");
??????Serial.print(millis()/1000);
??????Serial.println("?sec");?
??????imageName?=?uniqueFileName("png");?//generate?a?new,?uniqe?file?name
??????p.runShellCommand("fswebcam?/mnt/sda1/"?+?imageName);?//takes?the?picture
??????while(p.running());?//wait?till?the?process?ends
??????p.runShellCommand("madplay?/mnt/sda1/sounds/sirena.mp3");?//play?the?siren?sound
??????while(p.running());?//wait?till?the?process?ends
??????p.runShellCommand("python?/mnt/sda1/sendemail.py?/mnt/sda1/"?+?imageName);?//sends?the?picture?via?email
??????while(p.running());?//wait?till?the?process?ends
??????delay(50);
????}?????????
????takeLowTime?=?true;
??}
??if(digitalRead(pirPin)?==?LOW){???????
????digitalWrite(ledPin,?LOW);??//the?led?visualizes?the?sensors?output?pin?state
????if(takeLowTime){
??????lowIn?=?millis();??????????//save?the?time?of?the?transition?from?high?to?LOW
??????takeLowTime?=?false;???????//make?sure?this?is?only?done?at?the?start?of?a?LOW?phase
????}
????//if?the?sensor?is?low?for?more?than?the?given?pause,?
????//we?assume?that?no?more?motion?is?going?to?happen
????if(!lockLow?&&?millis()?-?lowIn?>?pause){??
??????//makes?sure?this?block?of?code?is?only?executed?again?after?
??????//a?new?motion?sequence?has?been?detected
??????lockLow?=?true;????????????????????????
??????Serial.print("motion?ended?at?");??????//output
??????Serial.print((millis()?-?pause)/1000);
??????Serial.println("?sec");
??????delay(50);
????}
??}
}
?
?
/*?A?simple?function?to?generate?unique?timestamp?based?filenames?*/
String?uniqueFileName(String?ext){
??String?filename?=?"";
??p.runShellCommand("date?+%s");
??while(p.running());?
??while?(p.available()>0)?{
????char?c?=?p.read();
????filename?+=?c;
??} ?
??filename.trim();
??filename?+=?"."?+?ext;
?
??return?filename;
}??
十秒鐘之后(校準時間),就將開始工作,并拍攝照片了!!!
一切搞定!下面這張照片,就是組裝完成后的效果圖。 在GitHub上 ,有這個項目的詳細文檔。
?via? makezine
關注硬創邦微信號(leiphone_bang),加入全球創客馬拉松主群(群號:259592983),參與我們的互動討論,獲得最新比賽信息~