星期日, 4月 14, 2013

Arduino筆記(十):製作ATMega328燒錄器

[2013/5/7]
做了幾個Arduino實驗後,思考接下來要做什麼呢?還有哪些還要深入研究的,遙控車?藍芽?網路模組等,都是看看還有哪些要再深入想要再深入瞭解的。無意間瀏覽到有拍賣的賣家再賣ATMega328的IC,有些是燒好Arduino主程式Bootloader,有的是只賣IC。剛好看到Arduino網站上有一篇介紹如何將Arduino板子設定為燒錄器ISP(In-System Programmer)的做法,將程式燒到麵包板上的ATMega328 IC,因此想買材料自己做看看。

[材料]

 Arduino Uno R3  x1
 ATMega328P-PU  x1
 16 MHz Crystal  x1
 10k 電阻  x1
 陶瓷電容器 18 to 22 pf.  x2

[接線圖及步驟]

要燒錄Bootloader 的步驟如下:
1. 將Arduino Uno R3接到電腦,開啟IDE畫面,設定好版子類型(Tool > Board > Arduino Uno)及正確的Serial Port (Tool > Serial Port > COM3) *注:要設定成可用的Port,不是每部電腦都設定為COM3。

2. 將ArduinoISP程式上傳到Arduino版子,ISP程式可在IDE介面 File > Open > Examples > ArduinoISP目錄內的ArduinoISP.ino 檔案,開啟後,上傳到Arduino 版子。

3. 將線路依照下列方式連接:



4. 選擇Arduino版的類型:Tools > Board > Arduino Duemilanove w/ ATmega328 或是Arduino Nano w/ ATmega328兩類都可以。



5. 設定為ISP:Tool > Programmer > Arduino as ISP
6. 開始燒錄:Run Tools > Burn Bootloader
我用小的麵包版,接起來的樣子是這樣:

這個方法在官方網站說只能用在Arduino Duemilanove w/ an ATmega328,無法使用在Arduino Uno及較舊 Arduino ATmega168版子,但是我用Arduino UNO R3確可以成功。

[參考資料]

 http://arduino.cc/en/Tutorial/ArduinoToBreadboard
Share:

星期六, 4月 13, 2013

Arduino筆記(九):DHT11溫濕度感應偵測與LCD顯示

[2013/04/07]
昨天從拍賣網站上購買的RaspBerry pi終於寄到了,順便買了測量溫濕度的DHT11及一個雙通道光耦合繼電器,利用今天空檔時,找了一下這個元件的Datasheet,也找了一段程式進行測試。


[材料]


• 麵包板 x 1
• Arduino Uno x 1
• DHT11溫濕度感應器 x1
• 4.7K電阻  x 1
•連接線 x 3條

[接線]

DHT11共有四隻腳,左邊第一隻腳接+5V,第二隻腳接Arduino Pin2,第四隻腳接地,比較特別的是第一、二隻腳還要用一個4.7K的電阻連接,



[程式一]


#include <dht11.h>
dht11 DHT11;  
#define DHT11PIN 7   //定義讀取資料的 Pin腳 
void setup() 
{
  Serial.begin(9600);
}

void loop()  
{
  Serial.println("\n");
  int chk = DHT11.read(DHT11PIN);
  Serial.print("Read sensor: ");
  switch (chk)
  {
    case 0: Serial.println("OK"); break;
    case -1: Serial.println("Checksum error"); break;
    case -2: Serial.println("Time out error"); break;
    default: Serial.println("Unknown error"); break;
  }

  Serial.print("Humidity (%): ");
  Serial.println((float)DHT11.humidity, 2);

  Serial.print("Temperature (oC): ");
  Serial.println((float)DHT11.temperature, 2);

  Serial.print("Temperature (oF): ");
  Serial.println(Fahrenheit(DHT11.temperature), 2);

  Serial.print("Temperature (K): ");
  Serial.println(Kelvin(DHT11.temperature), 2);

  Serial.print("Dew Point (oC): ");
  Serial.println(dewPoint(DHT11.temperature, DHT11.humidity));

  Serial.print("Dew PointFast (oC): ");
  Serial.println(dewPointFast(DHT11.temperature, DHT11.humidity));

  delay(2000);
}

/*-----( Declare User-written Functions )-----*/
//
// 計算轉換為華式
double Fahrenheit(double celsius)
{
        return 1.8 * celsius + 32;
}

//轉換為蘭式
double Kelvin(double celsius)
{
        return celsius + 273.15;
}

// dewPoint function NOAA
// reference: http://wahiduddin.net/calc/density_algorithms.htm 
double dewPoint(double celsius, double humidity)
{
        double A0= 373.15/(273.15 + celsius);
        double SUM = -7.90298 * (A0-1);
        SUM += 5.02808 * log10(A0);
        SUM += -1.3816e-7 * (pow(10, (11.344*(1-1/A0)))-1) ;
        SUM += 8.1328e-3 * (pow(10,(-3.49149*(A0-1)))-1) ;
        SUM += log10(1013.246);
        double VP = pow(10, SUM-3) * humidity;
        double T = log(VP/0.61078);   // temp var
        return (241.88 * T) / (17.558-T);
}

// 轉換為露點溫度

// delta max = 0.6544 wrt dewPoint()
// 5x faster than dewPoint()
// reference: http://en.wikipedia.org/wiki/Dew_point

double dewPointFast(double celsius, double humidity)
{
        double a = 17.271;
        double b = 237.7;
        double temp = (a * celsius) / (b + celsius) + log(humidity/100);
        double Td = (b * temp) / (a - temp);
        return Td;
}

[執行結果]




如果每次要開Serial Port的視窗,覺得很麻煩,心想如果把測到溫濕度值顯示在LCD上,那就方便多了,只要接上電源,就可以知道現在溫濕度的狀況,於是將線路與程式改寫,分別說明如下:



[材料]

• 麵包板 x 1
• Arduino Uno x 1
• DHT11溫濕度感應器 x1
• HD44780 相容 LCD x 1 (本實驗使用 16 pin 有背光 LCD)
• 旋轉式可變電阻 x 1
• 4.7K電阻 x 1
• 220K電阻 x 1
• 連接線 x N條


[程式二]


/*    將DHT11測得的溫濕度顯示在LCD顯示器 */ 

#include <liquidcrystal.h>    //使用LiquidCrystal Library 
#include <dht11.h>                 //使用DHT11 Library
LiquidCrystal lcd(12, 11, 5, 4, 3, 2);  //初始設定LCD顯示器的介面 
dht11 DHT11;     //定義DHT11 物件
#define DHT11PIN 7  //定義讀取資料的 Pin腳 

void setup() {     
   lcd.begin(16, 2);  // 設定LCD有2列16欄  
      Serial.begin(9600);  
} 

void loop() {  
   lcd.setCursor(0, 0); //將游標設定在第一行第一個位置(column 0, line 1)  
   int chk = DHT11.read(DHT11PIN);  //檢查DHT感測器的回應  

      switch (chk) {     
   case 0:       
     lcd.print("Humidity:");       
     lcd.print((float)DHT11.humidity, 1);       
     lcd.print("%");       
     lcd.setCursor(0, 1);       
     lcd.print("Tempure:");       
     lcd.print((float)DHT11.temperature, 1);       
     lcd.print("oC");     // 無法顯示度,只好用小寫的O表示       
           break;     
   case -1:       
     lcd.print("Checksum error"); 
     break;     
   case -2:       
     lcd.print("Time out error"); 
     break;     
   default:       
     lcd.print("Unknown error"); 
     break;   
   }  
   delay(1000); 
} 

[參考資料]

• http://arduino-info.wikispaces.com/DHT11-Humidity-TempSensor
Share:

星期六, 4月 06, 2013

Arduino筆記(八):控制步進馬達

[2013/04/06]
[2017/03/11] 更新
繼下午的Keypad與喇叭實作之後,晚上再拿出步進馬達來練習,當時買的套件之一就有附一個步進馬達及一個小模版,看了線路後,就將ULN2003APG這個 IC拆下來裝在麵包版上,看起來比較簡單些。我試著利用ULN2003這個 IC來推動步進馬達,並使用 Arduino 來控制步進馬達轉的角度,以下就試著連接線路,透過程式來進行控制。



[步進馬達]

有關步進馬達相關的知識,請參考:RASPBERRY PI 筆記(十二):控制步進馬達

[ULN2003]

ULN2003A,是一種高壓大電流的共發射極達林頓電晶體陣列 (Darlington Array )積體電路,內含 7組達林頓對管,每組對管的電流容量是500mA,輸出的電壓最高50V。該積體電路還整合了 7隻共陰極形式連接的續流二極體,用於電感性負載的開關動作的電流續流。[維基百科]

ULN2003 是一個反向器。所謂的反向器就是輸入是高電位時,輸出會是低電位,反之輸入低電位時,輸出會是高電位。

ULN2003A DIP封裝引腳圖 (來源:維基百科)

• 1B~7B:第一至第七組對管的基極    
• 1C~7C:第一至第七組對管的集電極
• E:公共發射極(一般接地)             
• COM:續流二極體共用陰極              

ULN2003在電子電路里的主要特點是大電流容量和高電壓輸出。常作爲驅動器使用,每組達林頓對管可並聯使用以達成更大的電流容量,甚至可以幾顆積體電路晶片堆疊並聯使用。步進馬達一般需要驅動器件有大電流輸出的能力,而微控制器等小電流的積體電路是不能直接驅動馬達的,因此可用作步進馬達的驅動器。

ULN2003內部的7組達林頓對管可以獨立操作,因爲它們的電路連接上除了發射極是一併接地共用E/GND引腳、續流二極體是共陰極接法共用一個COM引腳以外,集電極1C~7C以及基極1B~7B的引腳都是獨立對應的7組。若作爲步進馬達驅動器,則COM一端需要與步進馬達的公共供電端連接,爲馬達的反電動勢提供電流續流能力。

[Stepper Library]

Arduino IDE內有一個 Stepper Library,就是專門用來控制步進馬達的函式庫,以下是常用的函式:

Stepper(int steps, pin1, pin2, pin3, pin4):建立一個步進馬達的物件。
其中 step是指轉一圈所需的步數,假使馬達定義每步的角度,用360去除,就會得到步數。例如:Stepper myStepper = Stepper(100, 5, 6, 7, 8);  表示每一步為3.6度,轉一圈總共100步。

Stepper: setSpeed(long rpms):設定步進馬達每分鐘轉速 (RPMs) ,需為正數。
這個函式並不會讓馬達轉動,只是設定好轉速,當呼叫Step()函式時才會開始轉動。

Stepper: step(int steps):啟動馬達行進steps步數。setSpeed()定義速度,正的表示一個方向, 負數表示反方向。

步進馬達的型號是28BYJ-48, 5V DC,規格如下:

• 工作電壓: 5~12V DC
• 轉一圈步數:512 (搭配 1/64減速齒輪)
• 每分鐘圈數:80 RPM(Revolution per minute)
• 重量:37 公克

[材料]

• 麵包板 x 1
• Arduino Uno x 1
• 步進馬達(型號28BYJ-48, 5V DC) x1
• ULN2003APG x 1
•連接線 x N條

[接線]

步進馬達共有五條線,第一至第四條依序連接ULN2003APG的右側1-4接腳(即16~13接腳),第五條線則接上5V,Arduino的Pin11~Pin8依序接上ULN2003APG左側的1-4接腳(即1-4接腳),第8隻接腳連接GND。





[程式]

#include <Stepper.h>
#define STEPS 200  //定義步進馬達每圈的步數

//steps:代表馬達轉完一圈需要多少步數。如果馬達上有標示每步的度數,
//將360除以這個角度,就可以得到所需要的步數(例如:360/3.6=100)。(int)

Stepper stepper(STEPS, 11, 10, 9, 8);

void setup()
{
stepper.setSpeed(140);     // 將馬達的速度設定成140RPM 最大  150~160
}

void loop()
{
stepper.step(100);//正半圈
delay(1000);
stepper.step(-100);//反半圈
delay(1000);
stepper.step(200);//正1圈
delay(1000);
stepper.step(-200);//反1圈
delay(1000);
stepper.step(300);//正1圈半
delay(1000);
stepper.step(-300);//反1圈半
delay(1000);
stepper.step(1600);//正8圈
delay(1000);
stepper.step(-1600);//反8圈
delay(1000);
}

[參考資料]

• Arduino.cc: Stepper Library
• 維基百科:ULN2003A

Share:

星期五, 4月 05, 2013

Arduino筆記(七):3x4 Keypad 控制蜂鳴器發聲


[2013/04/05]
由於工作關係,隔了兩個多星期才又開始進行實驗,這次實驗的主題是從電料行買的3x4 Keypad,這個Keypad總共有八隻接腳,由於不知道行與列的線路連接方式,於是將拆開後背後的螺絲拆開看看線路圖:


仔細檢視每一個行(自右而左,分別為COL0 ~ COL2)與列(自上而下)的線路,知道接腳(從左至右)如下:

位置 KeyPad接腳 Arduino接腳
COL0
5
9
COL1
6
8
COL2
7
7
ROW0
1
13
ROW1
2
12
ROW2
3
11
ROW3
4
10

如要使用喇叭,Arduino有一個涵式庫已經定義好音調,只要用Include將"pitches.h"包含進來:
,以本單元的Do, Re ~ Si,總共七個,定義名稱如下:

#define NOTE_C5  523     // Do
#define NOTE_D5  587     // Re
#define NOTE_E5  659     // Me
#define NOTE_F5  698     // Fa
#define NOTE_G5  784    // So
#define NOTE_A5  880    // La
#define NOTE_B5  988    // Si

[材料]

• 麵包板 x 1
• Arduino 主板 x 1
• 3x4 Keypad x 1
• 喇叭 x 8
• 單心線 x 8

[接線]

將Keypad的第一隻腳接Pin 13,第二隻腳接Pin12,餘此類推至第八隻腳接Pin6,將喇叭的兩條線,一條接GND,一條接Pin4。





在畫Fritizing的電路圖時,內建沒有KeyPad圖形,可從http://code.google.com/p/fritzing/ 搜尋Keypad後下載Keypad.fzz匯入即可。雖然跟我買的Keypad圖樣不同,但是鍵盤排列位置是一樣的。

[程式]

// 引用 Keypad library
#include <Keypad.h>
#include <pitches.h>

// 3x4 Keypad
const byte ROWS = 4;  // 4 Rows
const byte COLS = 3;   // 3 Columns
int duration = 500;        // 500 miliseconds

// 定義 Keypad 的按鍵
char keys[ROWS][COLS] = {
  {'1','2','3'},
  {'4','5','6'},
  {'7','8','9'},
  {'*','0','#'}
};

// 定義 Keypad 連到 Arduino 的接腳
byte rowPins[ROWS] = {13, 12, 11, 10}; // 連到 Keypad 的 4 個 Rows: Row0, Row1, Row2, Row3 
byte colPins[COLS] = {9, 8, 7};   // 連到 Keypad 的 3 個 Columns: Column0, Column1, Column2

// 建立 Keypad 物件
Keypad keypad = Keypad( makeKeymap(keys), rowPins, colPins, ROWS, COLS );

void setup(){
  Serial.begin(9600); 
}
  
void loop(){
  // 讀取 Keypad 的輸入
  char key = keypad.getKey();
  
  // NO_KEY 代表沒有按鍵被按下
  if (key != NO_KEY){      // 假如有按鍵被按下,就印出按鍵對應的字元
      switch (key) {
     case '1':    
       tone(4, NOTE_C5, duration);
       break;
     case '2':    
       tone(4, NOTE_D5, duration);
       break;
     case '3':    
       tone(4, NOTE_E5, duration);
       break;
     case '4':    
       tone(4, NOTE_F5, duration);
       break;
     case '5':    
       tone(4, NOTE_G5, duration);
       break;
     case '6':    
       tone(4, NOTE_A5, duration);
       break;
     case '7':    
       tone(4, NOTE_B5, duration);
       break;       
     default:
       tone(4, NOTE_C8, duration);
     }
    Serial.println(key);
  }
}


[執行結果]

當按下數字1時,會發出Do的音,按下數字2時,會發出Re的音...直到
數字7為Si的音,其他鍵盤則為高音Do。




參考資料:
• Arduino Playground : The Matrix Keypad how-to
• Arduino  Examples > Digital I/O > Tone4
• Copper Maa:Arduino 筆記 – Lab6 控制蜂鳴器發聲
• Copper Maa:Arduino 筆記 – Lab18 讀取 3x4 Keypad 的輸入


Share: