2016年10月25日 星期二

檢測土壤濕度

氣候愈來愈多變,時而酷寒時而高溫燥熱,沒有腳不會躲也不會喊渴的植物該怎麼辦? 體貼的主人當然要想辦法知道他們甚麼時候會渴,及時地供水給他們,好讓他們能長的頭好壯壯。

目前用來檢測土壤濕度,最簡單的方式大都是利用兩根探針的導電程度來做判斷。底下這個實驗就是透過 Arduino 的 Serial Monitor 監測土壤濕度數據。




電路接線

雖然此模塊有提供數位腳位(D0)輸出,但為了要取得比較精確的數據,在這兒我們使用的是類比腳位(A0),電路接線如下:

Arduino    土壤濕度檢測模塊
5V            VCC
GND        GND
A0            A0


程式碼

void setup() {
  Serial.begin(9600);
}

void loop() {
  int v = analogRead(A0);
  Serial.println(v);
  delay(500);
}

裸露的銅片長度約為 38mm,依照版上孔洞的位置,可以把它區分為 9 等分。


將它放入乾燥的水杯中,



在完全乾燥的情況下,A0 腳位傳回的數值為 1020 左右。然後慢慢將自來水倒入杯中,逐一觀察並記錄水淹沒那 9 個區畫時讀到的數據如下:

9    400
8    440
7    480
6    510
5    540
4    570
3    620
2    680
1    800
0    1020



結論

由以上數據可知,土壤濕度愈大所讀取到的數值愈低;反之愈高。

這組數據並非絕對,因為影響的因素很多,包括濕度模塊的靈敏度,探針的材質、距離,水中的雜質,環境的溫濕度...等。不過若是作為簡便的土壤濕度檢測裝置,的確是措措有餘。

點偵測取樣的數據無法代表每一角落的土壤濕度,最好多放置幾組。另外,供水設備的灑水是否均勻,也是需要注意的。


相關連結

LM393 Datasheet http://www.onsemi.cn/pub_link/Collateral/LM393-D.PDF


採購資訊

土壤濕度檢測模塊 http://goods.ruten.com.tw/item/show?21642006632923

2016年10月23日 星期日

震動感測模塊 SW-18010P

一般市面上常見用來偵測震動的感測裝置大概有下列幾種:

1. 滾珠元件
2. 彈簧震動元件
3. Piezo
4. 加速度計

在這兒我們只針對彈簧震動感測模塊來做介紹。


 模塊採用一只 SW-18010P 彈簧震動元件,SW 表它是一個開關,在輸出腳位只輸出 0 或 1;18010 表外觀尺寸;P 表密封式封裝。詳細規格表如下:


如果剝除外包裝,就可以看到裡面有一個捲了非常多圈的細銅絲圍繞著主軸,



當它被晃動時細銅絲會接觸到主軸形成短路,這個信號經過 LM393 比較器處理之後,在 D0 腳位會輸出 LOW,此時指示燈會亮起。當然,在沒有震動時指示燈是熄滅的,在 D0 腳位會輸出 HIGH。

模塊板子上面有一個半固定可變電組,可以用來調節感測的靈敏度,逆時針旋轉時靈敏度會降低,順時針旋轉時靈敏度會升高。

這個模塊 A0 腳位是沒有作用的。


下面是模塊的電路圖



電路接線

Arduino    KY-002
5V             VCC
GND         GND
(詳程式)   D0


程式碼

這是一個最簡單的程式碼,只要有震動信號就會在序列視窗印出 "Shock Alarm"。
//sketch01.ino
int shockPin = 12;
int shockVal;

void setup ()
{
  Serial.begin(9600);
  pinMode (shockPin, INPUT);
}

void loop ()
{
  shockVal = digitalRead (shockPin);
  if (shockVal == LOW) Serial.println("Shock Alarm");
}

第 2 個程式碼我們要用外部中斷來接收震動信號,由於我們是用到第 0 個外部中斷,因此震動模塊的 D0 腳位要接到 Arduino 的 D2 腳位。

如果有震動信號 Arduino 板子 D13 腳位上面的 LED 就會亮 0.5 秒,然後熄滅。

#define SensorLED     13
#define SensorINPUT   2
unsigned char state = 0;
void setup()
{
  pinMode(SensorLED, OUTPUT);
  pinMode(SensorINPUT, INPUT);
  attachInterrupt(0, blink, FALLING); //D2口為外部中斷0,當有下降沿觸發的時候調用blink函數
}
void loop()
{
  if (state != 0)
  {
    state = 0;
    digitalWrite(SensorLED, HIGH);
    delay(500);
  }
  else
    digitalWrite(SensorLED, LOW);
}

void blink() //數字輸入傳感器下降沿觸發中斷服務函數
{
  state++;
}

上面兩個程式雖然可以隨時接收到震動信號,但如果不是要量測震動頻率,那麼在極短時間之內有太多的信號對我們來說是沒有助益的,例如 1 秒內接收到數十甚至數百次的信號。

針對上述問題改良,以下是第 3 個程式,在 0.25 秒內即使有多次震動信號,也只視為一次震動。

您可以嘗試變更 shockAlarmTime 的值,看看效果如何。

int shockPin = 12; // Use Pin 12 as our Input
int shockVal = HIGH; // This is where we record our shock measurement
boolean bAlarm = false;
unsigned long lastShockTime; // Record the time that we measured a shock
int shockAlarmTime = 250; // Number of milli seconds to keep the shock alarm high

void setup ()
{
  Serial.begin(9600); 
  pinMode (shockPin, INPUT) ; // input from the KY-002
}
void loop ()
{
  shockVal = digitalRead (shockPin) ; // read the value from our sensor 
  if (shockVal == LOW) // If we're in an alarm state
  {
    lastShockTime = millis(); // record the time of the shock
    // The following is so you don't scroll on the output screen
    if (!bAlarm){
      Serial.println("Shock Alarm");
      bAlarm = true;
    }
  }
  else
  {
    if( (millis()-lastShockTime) > shockAlarmTime  &&  bAlarm){
      Serial.println("no alarm");
      bAlarm = false;
    }
  }
}

結論

如果模塊在靜止狀態下持續有震動信號輸出,也就是指示燈持續亮著,此時要適度地調整半固定式可變電阻,將它慢慢往逆時針方向旋轉,一直到指示燈熄滅為止。然後再稍微晃動模塊,觀察是否有震動信號輸出,如果有表示 OK。

SW-18010P 元件在感測震動時沒有方向性,因此您可以將它隨便擺置。但根據個人經驗,還是建議您將此元件豎起來垂直地面,因為 SW-18010P 元件在製造時品質如果不是非常精良,或是裡面捲曲的細銅絲時間久了之後會因為重力下垂與主軸接觸而誤傳錯誤信號。

這個模塊雖然價格低廉,但它操作簡單易於使用,而且靈敏度也不錯,是個不錯的模塊。


相關連結

LM393 Datasheet http://www.onsemi.cn/pub_link/Collateral/LM393-D.PDF


採購資訊

震動傳感器模塊 http://goods.ruten.com.tw/item/show?21642006573589