2016年11月13日 星期日

自製紅外線遙控器

這裡我們不講硬體如何製作,而是說明如何用 Arduino 發射特定的紅外線編碼,藉以模擬出家裏的遙控器。


材料清單

接收部分
1. Arduino 開發板 *1
2. 紅外線接收模塊 *1
3. 杜邦線 *3P

發射部分
1. Arduino 開發板 *1
2. R1電阻 100R *1
3. 紅外線發射LED2 *1
4. 杜邦線 *2P


紅外線接收電路

電路接線和程式碼詳 http://pizgchen.blogspot.tw/2016/11/blog-post_13.html


紅外線發射電路

有三種電路方式,都可以作為紅外線發射電路,如下圖:


為方便起見我們採用左側那個電路,但實際應用時最好採用右側電路,因為發射信號的距離會比較遠。實際電路接線如下圖:




讓 Arduino 發射 38KHz 的信號

請您先將下列程式碼 Upload 到 Arduino,然後將紅外線發射管對準紅外線接收器,並開啟接收器的 Serial Monitor:

#include <IRremote.h>
IRsend irsend;

void setup() { }

void loop() {
  for (int i = 0; i < 3; i++) {
    irsend.sendSony(0xa90, 12); // Sony TV power code
    delay(100);
  }
  delay(1000);
}

您應該可以看到大概如下圖所示的畫面,在接收端的確有收到來自發射端發出的信號「A90」。



如果您夠仔細的話,應該會發現到雖然我們使用 D3 腳位作為發射紅外線信號,但我們並未在 setup() 區段內指定 D3 腳位的 pinMode 為 OUTPUT,那麼為什麼還可以正常發射 38KHz 信號呢? 因為 IRRemote Library 使用 Timer2 中斷,而 Timer2 是設定在 D3 腳位。

另外要提醒您,tone() 函式也是使用 Timer2 中斷,所以您如果同時使用 tone() 函式讓 Arduino 發出聲音,並且也使用 IRRemote Library 讓紅外線發射 38KHz 信號,您會發現它們無法同時作用。


發射紅外線編碼

Arduino 有內建許多廠商的紅外線編碼函式,如下

void sendNEC(unsigned long data, int nbits);
void sendSony(unsigned long data, int nbits);
void sendRC5(unsigned long data, int nbits);
void sendRC6(unsigned long data, int nbits);
void sendDISH(unsigned long data, int nbits);
void sendSharp(unsigned long data, int nbits);
void sendPanasonic(unsigned int address, unsigned long data);
void sendJVC(unsigned long data, int nbits, int repeat);


其實 KEYES 遙控器是採用 NEC 編碼格式,因此如果您想發出「1」的編碼,可以

irsend.sendNEC(0xFF6897, 32);

如果是未知廠商的編碼,您可以使用下列函式

void sendRaw(unsigned int buf[], int len, int hz);

以發射 KEYES 遙控器為例,如果要發射按鍵「1」的編碼,程式碼如下

unsigned int raw_1[68] = {0xB3,0x5A,0xB,0xC,0xB,0xC,0xB,0xD,0xA,0xC,0xB,0xD,0xA,0xD,0xA,0xD,0xA,0xD,0xA,0x22,0xB,0x22,0xA,0x22,0xA,0x23,0xA,0x22,0xA,0x22,0xB,0x22,0xB,0x21,0xB,0xC,0xB,0x22,0xA,0x22,0xB,0xC,0xB,0x22,0xB,0xC,0xA,0xD,0xB,0xC,0xA,0x22,0xB,0xC,0xB,0xC,0xB,0x22,0xB,0xC,0xA,0x22,0xB,0x22,0xB,0x21,0xB,};

irsend.sendRaw(raw_1,68,38);



進階題目

聲音函式和紅外線發射函式真的無法同時使用嗎? 答案是否定的。只要讓 tone() 函式和紅外線發射函式不使用同一個 Timer 中斷,如此即可解決問題,但此問題不在本文的討論範圍內。


相關連結

Timers and Interrupts http://letsmakerobots.com/node/28278


採購資訊

紅外線遙控器套件 http://goods.ruten.com.tw/item/show?21628077374704



找出紅外線遙控器的編碼

為了避免遙控器互相干擾,各家電器廠商大都會自訂該公司專屬的紅外線編碼,例如 SONY、JVC、PANASONIC...。

如果你家的遙控器壞掉了或是不見了,那該怎麼辦呢? 比較方便的方式就是再去買一支,再不然就是...自己做一支。

找出遙控器的編碼是一個關鍵,本文就是在說明如何找出遙控器編碼。


材料清單

1. Arduino 開發板
2. 紅外線接收模塊



電路接線

Arduino      紅外線接收模塊
VCC         中間腳(橙色線)
GND        「-」(綠色線)
D3            「S」(黃色線)


程式碼

以下程式可以找出大部分紅外線遙控器的編碼,包括 KEYES 紅外線遙控器套件的編碼。

#include <IRremote.h>

int RECV_PIN = 3;
IRrecv irrecv(RECV_PIN);
decode_results results;

void setup()
{
  Serial.begin(9600);
  irrecv.enableIRIn(); // Start the receiver
}

void loop() {
  if (irrecv.decode(&results)) {
    Serial.println(results.value, HEX);
    irrecv.resume(); // Receive the next value
  }
}

您可以發現 Serial Monitor 內的資料正是 KEYES 這款遙控器套件的編碼。



後記

南桃園電視盒的遙控器壓一次按鍵似乎會傳出數組編碼,而且好像不是那麼固定,我壓了數次「1」鍵,結果產生如下編碼,個人無法理解這編碼的規則性:



相關連結

IR receiver 1838 Datasheet https://arduino-info.wikispaces.com/file/view/IR-Receiver-AX-1838HS.pdf
紅外線遙控器 http://pizgchen.blogspot.tw/2016/11/blog-post.html


採購資訊

紅外線遙控器套件 http://goods.ruten.com.tw/item/show?21628077374704



紅外線遙控器

市售紅外線遙控器有很多種,硬體上我們在此僅介紹「KEYES」這一款紅外線遙控器套件,至於其它款式的原理及操作,其實也跟「KEYES」大同小異。



紅外線遙控器套件清單:
1. 遙控器 * 1
2. 接收模塊 *1
3. 5mm發射 LED *1
4. 杜邦線母母頭 * 3P


電路接線

這裡要注意的是, 接收模塊的腳位上面只有標示「S」和「-」,沒有標示「VCC」。這裏「S」表信號腳位(黃色杜邦線),「-」表 GND 腳位(綠色杜邦線),而中間那支腳就是 VCC (橙色杜邦線),詳下圖:



Arduino    紅外線接收模塊
VCC         中間腳(橙色線)
GND        「-」(綠色線)
D3            「S」(黃色線)


程式碼

#include "IRremote.h"

/*-----( Declare Constants )-----*/
int receiver = 3; // pin 1 of IR receiver to Arduino digital pin 3

/*-----( Declare objects )-----*/
IRrecv irrecv(receiver);           // create instance of 'irrecv'
decode_results results;            // create instance of 'decode_results'
/*-----( Declare Variables )-----*/

void setup()
{
  Serial.begin(9600);
  Serial.println("YourDuino IR Receiver Button Decode Test");
  irrecv.enableIRIn(); // Start the receiver
}

void loop()
{
  if (irrecv.decode(&results)) // have we received an IR signal?
  {
//    Serial.println(results.value, HEX);  UN Comment to see raw values
    translateIR();
    irrecv.resume(); // receive the next value
  }
}/* --(end main loop )-- */

/*-----( Declare User-written Functions )-----*/
void translateIR() // takes action based on IR code received
// describing KEYES Remote IR codes
{
  switch(results.value)
  {
  case 0xFF629D: Serial.println(" FORWARD"); break;
  case 0xFF22DD: Serial.println(" LEFT");    break;
  case 0xFF02FD: Serial.println(" -OK-");    break;
  case 0xFFC23D: Serial.println(" RIGHT");   break;
  case 0xFFA857: Serial.println(" REVERSE"); break;
  case 0xFF6897: Serial.println(" 1");    break;
  case 0xFF9867: Serial.println(" 2");    break;
  case 0xFFB04F: Serial.println(" 3");    break;
  case 0xFF30CF: Serial.println(" 4");    break;
  case 0xFF18E7: Serial.println(" 5");    break;
  case 0xFF7A85: Serial.println(" 6");    break;
  case 0xFF10EF: Serial.println(" 7");    break;
  case 0xFF38C7: Serial.println(" 8");    break;
  case 0xFF5AA5: Serial.println(" 9");    break;
  case 0xFF42BD: Serial.println(" *");    break;
  case 0xFF4AB5: Serial.println(" 0");    break;
  case 0xFF52AD: Serial.println(" #");    break;
  case 0xFFFFFFFF: Serial.println(" REPEAT");break;
  default:
    Serial.println(" other button   ");
  }// End Case

  delay(500); // Do not get immediate repeat
}

UPLOAD 程式到 Arduino 後,請開啟 Serial Monitor 並隨意按下遙控器按鍵,您就可以看到 Arduino 已正確接收到紅外線信號,如下圖:


至於程式裏面的紅外線編碼是怎麼來的,您可以參考「相關連結」裏的「找出紅外線遙控器的編碼」這篇文。



進階題目

遙控器上面有 0~9 共 10 個數字鍵,那麼遙控器只能按出 0~9 這樣的數字給 Ardunio 嗎? 答案是否定的。

我們可以在程式上指定一個字串變數用來儲存使用者按下的數字(其實它是字元),使用者每按下一個數字按鍵,便將這個字元結合到該字串變數尾端,一直遇到「#」字(註A),才將整組字串變數傳回,如此相當於遙控器按出一組數字信號。

一組數字信號是由多個字元組成,在傳輸過程中難免發生錯誤,所以我們應該要檢查這組資料的正確性。藉由檢查資料長度以及資料內容,可以確立傳輸的資料是否正確。您可以仿效紅外線編碼格式,指定一個前導字符和結尾字符,然後把固定長度的資料夾在其中,例如

*27584#

「*」表前導字符
「#」表結尾字符
27584 表傳輸的資料,它的資料長度是 5 碼

另外,濾除多次重覆按鍵也是一個課題。

當我們可以正確用紅外線發出一串數字編碼之後,我們可以用它來做哪些應用呢? 建議您可以試著去做一個紅外線遙控器密碼鎖來玩玩。

註:
A. 使用其它按鍵也可以,例如「*」鍵。


後記

1. 紅外線接收器容易受環境光源干擾,因此應避免將紅外線遙控裝置使用於戶外。
2. 如果您使用這樣的遙控器在您家的客廳搖控自走車,您可能會發現電視節目自己胡亂跳台,很明顯地這樣的紅外線遙控會干擾電器設備,因此要審慎使用。自訂遙控器編碼,或許可以解決這樣的問題。


相關連結

IR receiver 1838 Datasheet https://arduino-info.wikispaces.com/file/view/IR-Receiver-AX-1838HS.pdf
找出紅外線遙控器的編碼 http://pizgchen.blogspot.tw/2016/11/blog-post_13.html


採購資訊

紅外線遙控器套件 http://goods.ruten.com.tw/item/show?21628077374704











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


2016年9月28日 星期三

[MeArm.Rover] 火星探險車

MeArm.Rover 搭載 4 只直流強磁減速馬達,提供全時四輪傳動動力,搭配超大橡膠輪胎,完美的抓地效果讓 MeArm.Rover 即使遇到崎嶇不平的道路也如履平地般勇往前行。

MeArm.Rover 全方位的機械手臂可以讓您輕鬆排除障礙,搬開眼前的絆腳石;如果對象是個龐然大物,也可以透過超音波雷達安全地轉進。


MeArm.Rover 火星探險車是由一組機械手臂、紅外線循跡、超音波避障和四輪傳動動力系統所組成,以下將說明如何組裝MeArm.Rover 火星探險車。


一、準備材料

註:因為壓克力機構件改版的關係,您手上的版本比較新,可能與本文圖片有所不符,但還是能正常組裝。

機械手臂 *1
(請參考 http://pizgchen.blogspot.tw/2016/09/mearmrover_21.html 預先組裝好。)

動力系統 *1
(請參考 http://pizgchen.blogspot.tw/2016/09/mearmrover_16.htmlhttp://pizgchen.blogspot.tw/2016/09/mearmrover_18.html 預先組裝好。)

除上面材料外,我們還需要:

TT減速馬達 *2
輪胎 *2
馬達固定鐵件 *2


二、開始組裝

Step1 改造層板。

準備下列材料:
機械手臂

鬆開層板上的 4 只螺絲,將搖桿與層板取下,移除層板上的搖桿。


用 M3x12 螺絲、螺帽和墊圈各 4 只,將 Arduino 擴展板鎖到層板上。



將 2 只隔離柱往車體底板內側移動並鎖固。


移除方向輪,並用 4 套馬達固定鐵件將 4 只馬達輪胎固定到車體底板。(為清楚顯示先暫時移除機械手臂)


將層板歸位,用 4 只 M3x8 螺絲鎖固。


為防止電池盒在移動中掉落,建議您可以綁上一條橡皮筋圍繞四根隔離柱。


用 M3x8 螺絲、M3x20+6 隔離柱和螺帽各 2 只,將紅外線循跡模塊固定到車體底板。


用 M3x10 螺絲和螺帽各 1 只,將超音波避障模塊固定到車體底板。


這是完成的樣貌



三、電路接線

這裡要提醒的是,左前輪和左後輪兩組馬達電源線同時接在 L9110S 馬達驅動模塊的 MOTOR 埠,右前輪和右後輪兩組馬達電源線同時接在 L9110S 馬達驅動模塊的另一個 MOTOR 埠,其餘接線請詳循跡車與避障車這兩篇文。

由於同時驅動 4 只馬達需要較大的電流,所以 L9110S 馬達驅動模塊上面的電源可以考慮由電池盒直接供電。電池盒那兩條杜邦線即是供電給馬達驅動模塊,DC5521 插頭則是供電給 Arduino nano 擴展板。



您也可以使用兩組獨立電源,一組電源供電給 Arduino nano 擴展板,另一組電源供電給馬達驅動模塊,如此整體運作會更加穩定



採購資訊

meArm.Rover 火星探險車 https://goods.ruten.com.tw/item/show?21638708796647


2016年9月27日 星期二

[Servo] 指定舵機(伺服馬達)特定角度

為了在安裝機械手臂時不損壞機構件與伺服馬達,也為了在上電後不必為了不妥適的安裝而調整程式,為了避免在最壞的情況下打掉重練(拆掉重新組裝),在將塑膠片鎖固到馬達時,建議將下列程式 Upload 到 Arduino 板子裡,然後在上電的情況下組裝機械手臂。



電路接線

伺服馬達有3條線,紅色需接 5V,棕色需接 GND,橘色為訊號線,需接 Arduino 的腳位,電路接法如下:

Arduino      伺服馬達訊號線
D2              底座馬達
D3              右馬達
D4              左馬達
D5              夾子馬達


程式碼

#include <Servo.h>
Servo s1,s2,s3,s4;

void setup()
{
  s1.attach(2);
  s2.attach(3);
  s3.attach(4);
  s4.attach(5);

  s1.write(90); // 底座馬達
  s2.write(90); // 右馬達
  s3.write(170); // 左馬達
  s4.write(90); // 夾子馬達
}

void loop() {}


相關連結

SG90 Datasheet http://www.micropik.com/PDF/SG90Servo.pdf
MG90S Datasheet http://www.electronicoscaldas.com/datasheet/MG90S_Tower-Pro.pdf