Arduino Yún動作感測攝影機

五月 21, 2015
Facebook
Twitter
蒐集別人偷你東西的證據

「你敢碰就死定了」(You Can’t Touch This)專題,材料有紅外線動作感測器、攝影機和WiFi連線裝置(我選擇Arduino Yún,你也可以用Raspberry Pi)。你也可以連接擴音器,仿效警報器的聲音。

我的用意很明顯。不想讓孩子偷拿櫥櫃和冰箱的食物嗎?不想讓別人打開你的置物櫃嗎?想偷拍寵物偷吃東西的樣子嗎?想知道同事有沒有惡搞你的東西嗎?只要把這個裝置放在櫥櫃/冰箱/置物櫃,一旦偵測到動靜,就會馬上拍照,傳送至你的電子信箱!如果你採用IFTTT雲端平臺,小偷的照片還會自動上傳Facebook或Twitter,讓全世界都知道小偷的真面目!

這個專題很簡單,並不需要焊接/電子技術,幾分鐘即可組裝完成。


我說過我選擇Arduino Yún,一來方便使用,二來Wi-Fi設定很簡單,但價格比Raspberry Pi還要貴。不過,Arduino Yún做成的專題可以送人,任何人都會設定Arduino Yún的Wi-Fi,完全不用連接螢幕/滑鼠/鍵盤。 

材料

  • Arduino Yún
  • 紅外線動作感測器
  • 跟UVC相容的USB攝影機。別擔心,幾乎所有USB攝影機都跟UVC相容
  • MicroUSB電壓轉換器或USB電池組
  • Micro SD(建議)
  • USB音效卡(非必需)
  • USB集線器(非必需),如果同時有USB攝影機和USB音效卡,就需要集線器

步驟一:Arduino基本設定

  • 首先,你必須設定Arduino Yún的網路。只要照著指示做,應該會很簡單。
  • 測試你的網路連線:在瀏覽器鍵入 http://arduino.local,就會出現Arduino的網路介面。
  • 如果沒有問題,打開SSH對話框
    $ssh root@arduino.local
  • 預設密碼為「arduino」,再來安裝一些有用的套件
    $opkg update 
    $opkg install openssh-sftp-server
  • 為什麼是openssh-sftp-server呢?因為方便從Arduino上傳和下載檔案。現在你可以利用一般SFTP用戶端(FileZilla、Transmit或Cyberduck)來取代 SCP指令。我們還特別為了Python,安裝SSL支援套件(感謝sbkirby),因為這不在預設套件之內。
    $opkg install python-openssl
  • 我強烈建議在Arduino Yún放入micro SD,這會自動鑲嵌在/mnt/sda1。
  • 接著把USB攝影機和USB音效卡安裝到Arduino Yún。

步驟二:安裝並測試USB攝影機

  • 目前從opkg套件管理系統,可以取得Linino的UVC套件,安裝攝影機很省事,只要透過SSH即可連線,並且鍵入:
    $ opkg install kmod-video-uvc
  • 我們也需要拍攝軟體,我選擇fswebcam,不僅檔案小,也很容易使用。
    $ opkg install fswebcam

步驟三:拍攝第一張照片

  • 照片千萬要儲存在記憶卡,否則Arduino記憶體很快就滿了。如果你有使用記憶卡,記憶卡會鑲嵌在/mnt/sda1。如果沒有鑲嵌好,你最好找到FAT32檔案系統格式化過的micro SD,放進記憶卡插槽,重新啟動Arduino。
  • 現在把攝影機插到USB主機埠,並且鍵入:
    $ cd /mnt/sda1 
    $ fswebcam test.png
  • 一切順利的話,你會拍攝第一張照片!現在確認你的記憶卡空間。從此以後,你就能透過Bridge函式庫,從Arduino sketch拍照了,如下列所示:
    Process.runShellCommand(“fswebcam /mnt/sda1/test.png”);

步驟四(非必要):安裝音效卡

  • 打開SSH對話框,鍵入:
    $opkg install kmod-usb-audio
    $opkg install madplay
  • 現在Arduino Yún有音效卡了。我只試過MP3錄放裝置,但你可以嘗試錄製聲音。
  • 測試方法很簡單,只要複製一個MP3聲音檔到記憶卡,然後鍵入:
    $cd /mnt/sda1 
    $madplay yoursound.mp3
  • 從此以後,你就能透過橋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      = ‘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’
  • 更改寄件人、收件人等資料。
  • 現在透過SFTP(或SCP),把指令稿傳到Arduino Yún記憶卡,然後打開SSH對話框測試,鍵入:
    $cd /mnt/sda1 
    $python sendemail.py test.png
  • 不到幾秒鐘,你就會收到夾帶照片的信件!很神奇喔!

步驟六:建立電路

  • 別擔心,超簡單的,完全不需要焊接,只要組裝幾個零件。
  • 我選擇紅外線動作感測器,一來很可靠,二來方便使用。
  • 參考下列電路圖:
图片

  • 我連接了紅外線動作感測器,只要偵測到任何動靜,LED就會亮起。

動作七:該是上傳Arduino 草稿碼時候了!

  • 複製下列程式碼到Arduino IDE,並且上傳到Arduino 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; 
}

  • 10秒鐘後(校準時間)就會開始運轉拍照。組裝完成後的照片:

這個專題的所有檔案,都可以在我的GitHub網頁找到。希望大家會喜歡這個專題!祝福大家。

JEKO
傑柯身兼多職,是團體領導人、軟體工程師、開發者、和創業家,閒暇時熱愛下廚。
1998年創辦Interact SpA,2013年加入Mikamai,網路產業經驗超過16年。他從中學習到解決問題的能力,服務過小客戶、新創公司和複雜大環境,包括義大利政府網站以及大型通訊、傳播和時尚公司。
善用許多技術和團隊來建立可靠、可測量、可呈現的解決方案,目前把重心擺在物聯網上。

原文
(譯:謝明珊)

Social media & sharing icons powered by UltimatelySocial