Arduino 聲控開關
這樣敘述太沒個人特色,所以我將其命名為28開關,哈哈.
以下就以28開關為名稱來描述.
 
介紹視訊
控制方式
1. 先拍手2下,若28開關有聽到會讓喇叭嗶一聲.
2. 此時環境因須保持安靜, 等28開關回應嗶二聲.
3. 再拍手1下
4. 此時環境因須保持安靜, 等28開關回應嗶三聲.
5. 再拍手1下. 開關即會開或關
 
特色
1. 採用多重指令,防止28開關因環境音影響而誤動作.
2. 內含簡易的適應性控制,讓開關即使在環境音影響下,不會誤動作外,仍可進行操作.
 
 
給誰看的
本篇是寫給對28開關(聲控開關)有興趣,單純想動手做做玩玩看的朋友們.不須具備電子電路設計的能力,不須會撰寫程式的技巧.只需一點耐心,然後按照下列步驟,就可以擁有一個好玩的聲控開關囉.
 
步驟
1.準備材料
2.連接測試電路
3.上傳程式到裝置
4.連接開關電路
 
準備材料
1. Arduino Nano主控板x1(最好購買有Pin針的,這樣在線路配線時就可以用杜邦線直接插一插就好.)
 ArduinoNano加針.jpg     
 
2. Arduino 麥克風模組x1
麥克風模組.jpg
 
3. Arduino 繼電器模組x1
Arduino 聲控開關
 
4. 蜂鳴器x1
Arduino 聲控開關
 
5. LED燈x1
Arduino 聲控開關

6. Hi-Link 110V to 5V 電源模組
電源模組.jpg

7. 杜邦線
杜邦線.jpg

以上皆為露x拍賣上即可取的的材料.為防廣告嫌疑,就不另提供相關網址了.
利用上述關鍵字即可搜尋到.
 
連接測試電路
蒐集好材料後,按照下面測試電路圖,利用杜邦線將配線接好.之後即可開始驗證

實驗電路.jpg

 
上傳程式到裝置
要將程式上傳至裝置,需透過Arduino IDE這套軟體.
我的程式是用Arduino IDE 1.6.8開發的,所以為防止相容性問題,請下載跟我同版本的IDE.
下載Arduino IDE
首先至Arduino官網https://www.arduino.cc/.
點選SOFTWARE,如下圖.
Arduino 聲控開關
 
然後選擇以前的版本,如下圖.

Arduino 聲控開關

 

找到1.6.8版,下載,並安裝.如下圖.

Arduino 聲控開關

 

程式原始碼部份

// 28 Switch base on Arduino Nano
// Ver G4
// Date 2017-03-28
// Author: 30sec studio
//
#include "SoftwareSerial.h"
#define HITSEC     500  // 拍手間格秒數 < HITSEC
#define TRIGGERSEC 400  // 觸發後等待秒數 < TRIGGERSEC
#define TRIGGERVAL 15   // dB > 15開始取樣
#define TRIGGERMIN 5    // dB需低於 < 5
#define KEEPTIME   300  // 持續安靜300msec
#define MIC    A0
#define LED    A1 // A2-
#define BEEP   A3 // A4-
#define RELAY   2
#define RELAYB  7
SoftwareSerial Serial2(3, 4); // RX, TX
SoftwareSerial Serial3(5, 6); // RX, TX
int iSoundVal, iLED, iRelay, iStep, iAvgIp, iBlink;
int iDifference, iLoKeep;
int iEMax, iEKeep;
float fAvg, fdB;
int iAvgBuf30[30];
unsigned long lTimeStart, lTimeEnd, lTiming;
unsigned long lKeepStart, lKeepEnd;
//int newLineReceived = 0;
//String inputString = "";         // a string to hold incoming data
void setup()
{
  Serial.begin(115200);
  Serial2.begin(115200);
  Serial3.begin(115200);
  pinMode(MIC, INPUT);   
  pinMode(LED, OUTPUT);    // LED +
  pinMode(A2, OUTPUT);     // LED -
  pinMode(BEEP, OUTPUT);   // Beep
  pinMode(A4, OUTPUT);     // Beep-
  pinMode(RELAY, OUTPUT);
  pinMode(RELAYB, OUTPUT);
  analogWrite(A1, 0x00);
  analogWrite(A2, 0x00); // LED -
  analogWrite(A4, 0x00); // Beep-
  digitalWrite(RELAY, HIGH);
  digitalWrite(RELAYB, HIGH);
  iStep = 0;         // init data
  iLED = 0;          // init data 0,Off  1,On
  iRelay = 0;        // init data 0,Off  1,On
  iAvgIp = 0;        // init data
  lTimeStart = 0;
  for (int i = 0; i < 30; i++) // init data
  {
    iAvgBuf30[i] = analogRead(MIC);
  }
  for (int i = 0; i < 2; i++)
  {
 tone(BEEP, 350);
 delay(100);     
 noTone(BEEP);   
 delay(100);     
  }
  iEMax = 0;
  iEKeep = 0;
}
void loop()
{
 int iTemp;
 //Serial2.println(analogRead(MIC));
 Flash_dB();
 SamplingIII();
 if (iStep == 0)
 {
  //Serial.print("Val: ");
  //Serial.print(analogRead(MIC));
  //Serial.print("   ");
  //Serial.print(fdB / 1.0f);
  //Serial.print("   ");
  if (fdB > fAvg)
  {
   iTemp = fdB - fAvg;
  }
  else
  {
   iTemp = fAvg - fdB;   
  }
  //Serial.print(iTemp);
  Serial3.println(iTemp);
  if (iEMax > iTemp + 20)
  {
   if (iEKeep > 50)
   {
    iEKeep = 0;
    iEMax = iEMax-1;
   }
   iEKeep++;
  }
  else
  {
   iEKeep = 0;
  }
  if (iTemp > iEMax)
  {
   iEMax = iTemp;
  }
  //Serial.print("  ");
  //Serial.println(iEMax);
  //Serial2.println(iEMax);
 }
}
void SamplingIII()
{
 int iTemp;
 // iStep = 11
 if(iStep == 11)
 {
  iBlink = 0;
  lKeepStart = millis(); // init data
  lKeepEnd = millis();   // init data
  while ((lKeepEnd - lKeepStart) < KEEPTIME)
  {
   lKeepEnd = millis();
   Flash_dB();
   if (iDifference > iEMax+ TRIGGERMIN)  
   {
    iEMax+= TRIGGERMIN;
    lKeepStart = millis(); // init data
    lKeepEnd = millis();   // init data
    Serial.print("11 : ");        // for debug
    Serial.println(iDifference);  // for debug
    Serial3.println(iDifference); // for debug
   }
   if ((iBlink > 100) && (iLED == 0))
   {
    iBlink = 0;
    iLED = 1; // init data 0,Off  1,On
    analogWrite(LED, 0x80);
   }
   if ((iBlink > 100) && (iLED == 1))
   {
    iBlink = 0;
    iLED = 0; // init data 0,Off  1,On
    analogWrite(LED, 0x00);
   }
   iBlink++;
  }
  analogWrite(LED, 0x00);
  iLED = 0;      
  iStep = 0;     
  lTimeStart = 0;
 }
 
 if ((iStep == 0) || (iStep == 2))
 {
  Flash_dB();
  if (iDifference > iEMax+ TRIGGERVAL)
  {
   if (iStep == 0)
   {
    lTimeStart = millis();
    iStep = 1;
    Serial.println(" 1 : ");
   }
   else if (iStep == 2)
   {
    iStep = 3; // Step 3
    Serial.println(" 3 : ");
   }
   iLoKeep = 0;
  }
 }
 
 if ((iStep == 1) || (iStep == 3)) // iStep On
 {
  Flash_dB();
  if (iDifference < iEMax+ TRIGGERMIN)
  {
   iLoKeep++;
   if (iLoKeep > 50)
   {
    if (iStep == 1)
    {
     iStep = 2; // Step 2
     Serial.println(" 2 : ");
    }
    else if (iStep == 3)
    {
     iStep = 4; // Step 4
     Serial.println(" 4 : ");
     tone(BEEP, 10);
     delay(200);    
     noTone(BEEP);  
     delay(200);    
    }
   }
  }
 }
 if (iStep == 4)
 {
  Serial.println(" 5 : ");
  lKeepStart = millis(); // init data
  lKeepEnd = millis();   // init data
  while ((lKeepEnd - lKeepStart) < KEEPTIME)
  {
   lKeepEnd = millis();
   Flash_dB();
   if (iDifference > iEMax+TRIGGERMIN)
   {
    iStep = 11;
    lTimeStart = 0;
    lKeepEnd = KEEPTIME + 1;
    Serial.println("Keep Error!\n"); // for debug
   }
  }
  if (iStep == 4)
  {
   for (int i = 0; i < 2; i++)
   {
    tone(BEEP, 10);
    delay(50);     
    noTone(BEEP);  
    delay(50);     
   }
   iStep = 6;
   Serial.println(" 6 : ");
   lTimeStart = millis();
  }
 }
 if ((iStep == 6) || (iStep == 8))
 {
  Flash_dB();
  if (iDifference > iEMax+ TRIGGERVAL)
  {
   if (iStep == 6)
   {
    lTimeStart = millis();
    iStep = 7;
    Serial.println(" 7 : ");
    tone(BEEP, 10);
    delay(200);    
    noTone(BEEP);  
    delay(200);    
   }
   else if (iStep == 8)
   {
    iStep = 9;
    Serial.println(" 9 : ");
   }
   iLoKeep = 0;
  }
 } 
 if ((iStep == 7) || (iStep == 9)) //
 {
  Flash_dB();  
  if (iStep == 7)
  {
   lKeepStart = millis();
   lKeepEnd = millis();  
   Serial.println(" 8 : ");  
   while ((lKeepEnd - lKeepStart) < KEEPTIME)
   {
    lKeepEnd = millis();
    Flash_dB();
    if (iDifference > iEMax+ TRIGGERMIN)
    {
     lKeepStart = millis();
     lKeepEnd = millis();  
     Serial.print(" 8 : Error dB: ");
     Serial.println(iDifference);
     iStep = 11;
     lTimeStart = 0;
     break;
    }
   }
   if (iStep == 11)
   {
    // do notiing
   }
   else
   {
    iStep = 8; // Step 8
    for (int i = 0; i < 3; i++)
    {
     tone(BEEP, 10);
     delay(50);     
     noTone(BEEP);  
     delay(50);     
    }
    lTimeStart = millis();
   }
  }
  else if (iStep == 9)
  {
   if (iStep == 9)
   {
    Serial.println("10 : ");
    lTimeEnd = millis();
    if ((lTimeEnd - lTimeStart) < HITSEC)
    {
     if (iRelay == 0)
     {
      iRelay = 1; // init data 0,Off  1,On
      digitalWrite(RELAY, LOW); // Digi Sig
      digitalWrite(RELAYB, LOW); // Digi Sig
     }
     else
     {
      iRelay = 0; // init data 0,Off  1,On      
      digitalWrite(RELAY, HIGH); // Digi Sig
      digitalWrite(RELAYB, HIGH); // Digi Sig
     }
     tone(BEEP, 10); 
     delay(200);     
     noTone(BEEP);   
     delay(200);     
     iStep = 11;
     lTimeStart = 0;
    }
    else
    {
     iStep = 11;
     lTimeStart = 0;
    }
   }
  }
 }
 if (lTimeStart != 0)
 {
  lTiming = millis();
  if ((lTiming - lTimeStart) > TRIGGERSEC)
  {
   iStep = 11;
   lTimeStart = 0;
   Serial.println("Over Time!"); 
  }
 }
 Serial.print("iStep: ");
 Serial.println(iStep);
}
void Flash_dB()
{
 iSoundVal = analogRead(MIC);
 if (iAvgIp >= 30)
 {
  iAvgIp = 0;
 }
 iAvgBuf30[iAvgIp] = abs(iSoundVal);
 iAvgIp++;
 
 fAvg = 0;
 for (int i = 0; i < 30; i++)
 {
  fAvg = fAvg + iAvgBuf30[i];
 }
 fAvg = fAvg / 30.0f;
 
 fdB = iSoundVal;
 if (fdB > fAvg)
 {
  iDifference = fdB - fAvg; 
 }
 else
 {
  iDifference = fAvg - fdB;
 }
}

 

開啟Arduino IDE軟體.
設定裝置及COM位置,若不知道設定方式或使用方式,請參考我的另一篇文章"Arduino IDE"
http://thirtysec.pixnet.net/blog/post/222467340
建立一個新檔案,然後將原始碼完整的覆蓋在新檔案的內容,如下圖.

Arduino 聲控開關

將程式碼上傳至裝置,即可測試.
 
測試影片
這段測試影片,是我原始碼寫到G3時就已錄製,所以跟介紹影片不太一樣,請多包涵.哈哈
操作方式跟介紹影片(G4版本)一樣,若你測試結果是一樣的,那你就成功一半了.
 
連接開關電路
這是最後的步驟,因為這步驟會用到電壓110V所以製作這個步驟請務必小心

實作電路.jpg

電路圖如上.因為要做成成品.接下來連接的部分就請個位發揮巧思.裝到你想裝的地方啦.
我的想法是,想將這電路裝入延長線,這樣就可以把一般的延長線改裝成聲控的延長線了.
但...延長線買太小了,以至於塞不進去,所以只好外露大部分的元件-_-|||
再加上外殼跟元件的不合,所以我用了熱熔膠來固定元件.
最後.附上我的成品圖給各位參考.
 
28開關內部
Arduino 聲控開關
 
28開關外觀1
Arduino 聲控開關
 
28開關外觀2

Arduino 聲控開關

 

創用 CC 授權條款
Arduino聲控開關/28開關Peng Yi Hsing製作,以創用CC 姓名標示-非商業性-相同方式分享 3.0 台灣 授權條款釋出。

 

arrow
arrow
    創作者介紹
    創作者 30sec 的頭像
    30sec

    30sec studio

    30sec 發表在 痞客邦 留言(0) 人氣()