Más contenido relacionado La actualidad más candente (20) Similar a Arduino感測應用 (20) Más de 吳錫修 (ShyiShiou Wu) (20) Arduino感測應用3. Makeeachdaycount
X ? Y : Z
若X為true,執行Y,否則執行Z
範例
if (analogRead(CDS) < threshold)
ledState = HIGH;
else
ledState = LOW;
上述程式碼可改寫如下:
ledState = (analogRead(CDS) < threshold)? HIGH : LOW;
三元運算子
3
5. Makeeachdaycount
參考程式
#define LED 2
#define CDS A0
bool ledState = LOW; //目前輸出腳位之狀態
int threshold = 600; //CDS亮度開關臨界值,視需要調整
int lightness;
void setup() {
pinMode(LED, OUTPUT);
pinMode(CDS, INPUT);
}
void loop() {
lightness = analogRead(CDS);
ledState = (lightness < threshold)? HIGH : LOW;
digitalWrite(LED, ledState);
}
Lab 自動小夜燈 2/2
5
6. Makeeachdaycount
麥克風將聲波轉換為電子訊號
動圈式麥克風(Dynamic Microphone)
當聲波進入麥克風,振膜受到聲波的壓力而產生振
動,與振膜連接在⼀起的線圈則開始在磁場中移動
產生感應電流
聲音感測 1/2
6
電容式麥克風(Condenser Microphone)
當聲波進入麥克風,振動膜和基板之間的距離會隨著振動而改變電容值;
敏感度高,常見於錄音室使用
聲音
訊號輸出
感應磁鐡感應線圏
拾音薄膜
振動膜
電阻
電池
訊號輸出
基板
聲音
9. Makeeachdaycount
參考程式
#define MIC A2
void setup() {
pinMode(MIC, INPUT);
Serial.begin(9600);
}
void loop() {
Serial.println(analogRead(MIC));
delay(10);
}
選單命令Tools>Serial Plotter
Lab聲音感測 2/2
9
12. Makeeachdaycount
參考程式
#define RED_LED 12
#define MIC A2
int threshold = 600; //音量開關臨界值
int normal = 100; //正常情況音量值
bool ledState = LOW; //目前輸出腳位之狀態
void setup() {
pinMode(RED_LED, OUTPUT);
pinMode(MIC, INPUT);
}
void loop() {
if (analogRead(MIC) > threshold) { //聲音觸發
do { //等回復靜音
//do nothing
} while (analogRead(MIC) > normal);
ledState = !ledState; //切換輸出狀態
digitalWrite(RED_LED, ledState);
}
}
Lab 聲控開關 2/2
12
16. Makeeachdaycount
CapacitiveSensor藉由量測Send pin與Receive Pin之間狀態切換之
延遲情形,提供⼀個相對數值,
CapacitiveSensor類別方法
CapacitiveSensor(byte sendPin, byte receivePin)
建構CapacitiveSensor物件
sendPin輸出檢測訊號之接腳
receivePin讀取觸控訊號之接腳
電阻R建議值1MΩ~10MΩ,receivePin連接100pF電容接地可增加檢測
穩定性
CapacitiveSensor函式庫 2/4
16
17. Makeeachdaycount
long capacitiveSensorRaw(byte samples)
傳回總感應電容對應值
samples取樣數,較大值分辦率較佳但會降低程式效能;建議值30
long capacitiveSensor(byte samples)
傳回感應電容變化對應值 (總感應電容對應值 – 基準感應電容對應值)
samples取樣數,較大值分辦率較佳但會降低程式效能;建議值30
void set_CS_Timeout_Millis(unsigned long timeout_millis)
設定量測逾時時間,預設為2000毫秒 (2秒)。發射端 (Send pin) 訊號準
位變換後,會開始檢測感應端 (Receive pin) 訊號何時跟隨變化,在檢
測期間,其它程式會暫停運作,所以必須設定逾時時間
CapacitiveSensor函式庫 3/4
17
18. Makeeachdaycount
void reset_CS_AutoCal()
立即校正capacitiveSensor函式的感應電容基準值
void set_CS_AutocaL_Millis(unsigned long autoCal_millis)
設定自動校正capacitiveSensor函式的基準感應電容值的時間間隔,設
定為0xFFFFFFFF可關閉自動校正功能
CapacitiveSensor函式庫 4/4
18
20. Makeeachdaycount
參考程式
#include <CapacitiveSensor.h> //引用CapacitiveSensor函式庫
CapacitiveSensor cs = CapacitiveSensor(2,3); //建構CapacitiveSensor物件
void setup() {
cs.reset_CS_AutoCal(); //校正感應電容基準值
cs.set_CS_AutocaL_Millis(180000); //每隔3分鐘自動校正感應電容基準值
Serial.begin(9600);
}
void loop() {
Serial.print(cs.capacitiveSensorRaw(30)); //讀取總感應電容值
Serial.print("t");
Serial.println(cs.capacitiveSensor(30)); //讀取感應電容變化值
delay(100);
}
Lab 電容式近接感應值測試 2/3
20
23. Makeeachdaycount
參考程式
#include <CapacitiveSensor.h> //引用CapacitiveSensor函式庫
#define LED 4
int threshold = 1000;
bool ledstate = LOW;
int cs_value;
CapacitiveSensor cs = CapacitiveSensor(2,3); //建構CapacitiveSensor物件
void setup() {
pinMode(LED, OUTPUT);
cs.reset_CS_AutoCal(); //校正感應電容基準值
Serial.begin(9600);
}
Lab 電容式近接開關 2/3
23
27. Makeeachdaycount
參考程式
#define RED_LED 3
#define TOUCHPAD 2
bool ledState = LOW;
void setup() {
pinMode(RED_LED, OUTPUT);
pinMode(TOUCHPAD, INPUT);
}
void loop() {
if (digitalRead(TOUCHPAD)==HIGH) { //碰觸感應端
ledState = !ledState;
digitalWrite(RED_LED, ledState);
do {
} while (digitalRead(TOUCHPAD)==HIGH); //等待放開
}
}
Lab 觸控開關 2/2
27
33. Makeeachdaycount
int decode (decode_results *results)
嘗試解碼所接收到的紅外線訊息並儲存到results結構變數,成功的話回
傳true,否則傳回false
void enableIRIn()
啟用IR接收
void resume()
重新啟用IR接收
IRRemote程式庫 2/4
33
34. Makeeachdaycount
decode()函式會將接收資料解碼存入decode_results結構變數
class decode_results{
public:
decode_type_t decode_type; //UNKNOWN, NEC, SONY, RC5, ...
unsigned int address; //Used by Panasonic & Sharp [16-bits]
unsigned long value; //Decoded value [max 32-bits]
int bits; //Number of bits in decoded value
volatile unsigned int *rawbuf; //Raw intervals in 50uS ticks
int rawlen; //Number of records in rawbuf
int overflow; //true iff IR raw code too long
};
其中decode_type_t是在IRremote.h檔案中宣告的列舉資料
typedef enum {
UNKNOWN = -1, UNUSED = 0, RC5, RC6, NEC, SONY, PANASONIC, JVC, SAMSUNG, WHYNTER,
AIWA_RC_T501, LG, SANYO, MITSUBISHI, DISH, SHARP, DENON, PRONTO, LEGO_PF,
} decode_type_t;
IRRemote程式庫 3/4
34
35. Makeeachdaycount
IRsend類別方法
IRsend()
預設使用D3連接到紅外線發射器
void sendWhynter (unsigned long data, int nbits)
data 要傳送之資料值
nbits 傳送的資料值所佔位元數
針對其它廠牌紅外線傳輸協定,還有sendNEC()、 sendSony()、
sendRC5()、 sendRC6()、 sendSharpRaw()、 sendJVC()、
sendSAMSUNG()等方法,方法參數用法相同
如果IRrecv無法正確解碼所接收到的紅外線訊息,可更換不同的紅外線
傳輸協定方法試試
IRRemote程式庫 4/4
35
37. Makeeachdaycount
參考程式
#include <IRremote.h> //引用IRRemote函式庫
const byte irReceiverPin = 2; //紅外線接收器OUTPUT訊號接在D2
const byte LED = 4; //D4接指示燈
IRrecv irrecv(irReceiverPin, LED); //建立IRrecv物件來接收紅外線訊號
decode_results ir_results; //用來儲存解碼結果之decode_results結構變數
void setup() {
irrecv.blink13(true); //啟用接收指示
Serial.begin(9600);
irrecv.enableIRIn(); //啟動IR接收
}
Lab IR遙控器訊號測試 2/3
37
38. Makeeachdaycount
void loop() {
if (irrecv.decode(&ir_results)) { //解碼成功,收到⼀組紅外線訊號
Serial.println(ir_results.value, HEX); //紅外線控制碼
irrecv.resume(); //繼續收下⼀組紅外線訊號
}
delay(100);
}
Lab IR遙控器訊號測試 3/3
38
40. Makeeachdaycount
參考程式
#include <IRremote.h> //引用IRRemote函式庫
const byte irReceiverPin = 2; //紅外線接收器OUTPUT訊號接在D2
const byte LED = 4; //D4接指示燈
IRrecv irrecv(irReceiverPin); //建立IRrecv物件來接收紅外線訊號
decode_results ir_results; //用來儲存解碼結果之decode_results結構變數
void setup() {
pinMode(LED, OUTPUT); //啟用接收指示
Serial.begin(9600);
irrecv.enableIRIn(); //啟動IR接收
}
Lab IR遙控LED 2/3
40
41. Makeeachdaycount
void loop() {
if (irrecv.decode(&ir_results)) { //解碼成功,收到⼀組紅外線訊號
switch (ir_results.value) {
case 0xFF6897: //按鍵0控制碼,須依遙控器實測結果調整
digitalWrite(LED, LOW);
break;
case 0xFF30CF: //按鍵1控制碼,須依遙控器實測結果調整
digitalWrite(LED, HIGH);
break;
}
Serial.println(ir_results.value, HEX); //紅外線控制碼
irrecv.resume(); //繼續收下⼀組紅外線訊號
}
delay(100);
}
Lab IR遙控LED 3/3
41
44. Makeeachdaycount
Arduino A參考程式
#include <IRremote.h> //引用IRRemote函式庫
const byte SW = 5;
IRsend irsend; //建立IRsend物件來傳送紅外線訊號 (使用D3)
bool lastState = HIGH; //前⼀次開關腳位之狀態
bool ledState = LOW; //LED輸出狀態
byte click = 0;
void setup() {
pinMode(SW, INPUT_PULLUP);
Serial.begin(9600);
}
Lab IR傳輸應用 3/6
44
45. Makeeachdaycount
void loop() {
bool b1 = digitalRead(SW); //讀取開關目前狀態
if (b1 != lastState) { //開關狀態改變
delay(20); //防彈跳
if (b1 == digitalRead(SW)) { //再次確認開關狀態
lastState = b1;
click++;
}
}
if (click == 2){ //已Click開關
click = 0;
Serial.println("IR send");
irsend.sendRC5(0xA0A0A0, 24); //IR送出控制碼
}
delay(100);
}
Lab IR傳輸應用 4/6
45
46. Makeeachdaycount
Arduino B參考程式
#include <IRremote.h> //引用IRRemote函式庫
const byte irReceiverPin = 2; //紅外線接收器OUTPUT訊號接在D3
const byte LED = 4; //D4接指示燈
IRrecv irrecv(irReceiverPin); //建立IRrecv物件來接收紅外線訊號
decode_results ir_results; //用來儲存解碼結果之decode_results結構變數
void setup() {
pinMode(LED, OUTPUT);
Serial.begin(9600);
irrecv.enableIRIn(); //啟動紅外線解碼
}
Lab IR傳輸應用 5/6
46
47. Makeeachdaycount
void loop() {
if (irrecv.decode(&ir_results)) { //解碼成功,收到⼀組紅外線訊號
switch (ir_results.value) {
case 0xA0A0A0: //收到正確的控制碼
ledState = !ledState;
digitalWrite(LED, ledState);
break;
}
Serial.println(ir_results.value, HEX);
irrecv.resume(); //繼續收下⼀組紅外線訊號
}
delay(100);
}
Lab IR傳輸應用 6/6
47
51. Makeeachdaycount
byte incoming = shiftIn(dataPin, clockPin, bitOrder);
從dataPin腳位讀取位元資料,讀取8位元後存入incoming變數中
clockPin為送出觸發讀取信號之腳位
bitOrder指定位元資料讀取順序,MSBFIRST或LSBFIRST
範例
#define TC77_SIO 11
#define TC77_SCK 12
...
val1 = shiftIn(TC77_SIO, TC77_SCK, MSBFIRST);
Lab 溫度感測 2/4
51
52. Makeeachdaycount
參考程式
#define TC77_SIO 11
#define TC77_SCK 12
#define TC77_CS 13
int value;
float tempC, tempF;
void setup() {
pinMode(TC77_CS, OUTPUT);
pinMode(TC77_SIO, INPUT);
pinMode(TC77_SCK, OUTPUT);
Serial.begin(9600);
}
Lab 溫度感測 3/4
52
53. Makeeachdaycount
void loop() {
byte val1, val2;
digitalWrite(TC77_CS, LOW); //設定CS為LOW,準備讀取資料
val1 = shiftIn(TC77_SIO, TC77_SCK, MSBFIRST); //讀取high byte
val2 = shiftIn(TC77_SIO, TC77_SCK, MSBFIRST); //讀取low byte
digitalWrite(TC77_CS, HIGH); //完成讀取,CS回復為HIGH
value = val1*256 + val2;
tempC = (value>>3) * 0.0625; //去除最低3位元後轉換為10進制溫度值
tempF = tempC * 1.8 + 32; //換算華氏溫度值
Serial.print("Temperature:");
Serial.println(tempC, 2);
delay (5000);
}
Lab 溫度感測 4/4
53
58. Makeeachdaycount
參考程式
#include <DHT.h> //引用IRRemote函式庫
#define DHTPIN 7
#define DHTTYPE DHT11
DHT dht(DHTPIN, DHTTYPE, 0);
void setup() {
pinMode(DHTPIN, INPUT);
Serial.begin(9600);
dht.begin();
}
Lab 溫濕度感測 2/3
58
59. Makeeachdaycount
void loop() {
float h = dht.readHumidity(); //讀取濕度值
float t = dht.readTemperature(); //讀取溫度值
Serial.print("Humidity: ");
Serial.print(h, 1); //顯示溫度值 (小數點1位)
Serial.print("%t Temperature: ");
Serial.print(t, 1); //顯示濕度值 (小數點1位)
Serial.println("C");
delay(10000);
}
Lab 溫濕度感測 3/3
59
60. Makeeachdaycount
超音波 (ultrasound) 是指任何頻率超過人類耳朵可以聽到的最高閾值
20KHz之聲波或振動
音速 = 331.31 1
.
在⼀大氣壓、25°C時音波在空氣中之波速約為 346m/s
蝙蝠利用生物聲納 (biosonar) 回音定位 (echolocation) 來捕捉獵物或
躲避障礙物
超音波測距原理 1/2
60
Emitted Wave of Bat
Reflected Wave of Prey
62. Makeeachdaycount
HC-SR04
精度:3mm
距離範圍:2cm ~ 450cm
有效的角度:<15℃
觸發輸入信號:10uS TTL pulse
超音波感測器 1/2
62
Signal
Internal
Initiate Echo back
10uS TTL to trigger pin
Pulse width corresponds to distance
(about 150uS-25mS, 38mS if no obstacle)
Formula:
pulse width (uS) * 0.0346 (cm/uS) / 2
Ultrasonic Transducer will issue 8 40kHz pulse
63. Makeeachdaycount
duration = pulseIn(pin, value);
duration = pulseIn(pin, value, timeout);
檢測脈波寛度,工作範圍10 us~3 minutes
pin:信號接腳
value:要偵測的脈波類型,HIGH或LOW
timeout:等待脈波起始之時間(us),預設為1秒
回傳值表示脈波寬度 (單位us),0表示timeout前沒有脈波起始
超音波感測器 2/2
63
65. Makeeachdaycount
參考程式
#define TRIG 6
#define ECHO 5
long duration;
int distance;
void setup() {
pinMode(TRIG, OUTPUT);
pinMode(ECHO, INPUT);
Serial.begin(9600);
}
Lab 超音波測距 2/3
65
66. Makeeachdaycount
void loop() {
digitalWrite(TRIG, LOW); //Clears the trig pin
delayMicroseconds(2);
digitalWrite(TRIG, HIGH); //從Trig送出10 us脈波
delayMicroseconds(10);
digitalWrite(TRIG, LOW);
duration = pulseIn(ECHO, HIGH); //讀取Echo脈波寬度(us)
distance= duration * 0.0346 / 2; //換算為距離(cm)
Serial.print("Distance: "); //在Serial Monitor顯示距離值
Serial.print(distance, 1);
Serial.println(" cm");
delay(3000);
}
Lab 超音波測距 3/3
66
70. Makeeachdaycount
參考程式
#define PIRSensor 8
#define LED 12
void setup() {
pinMode(PIRSensor, INPUT);
pinMode(LED, OUTPUT);
}
void loop() {
int sensorValue = digitalRead(PIRSensor);
if (sensorValue == HIGH)
digitalWrite(LED, HIGH);
else
digitalWrite(LED, LOW);
}
Lab PIR人體移動感測 2/2
70
71. Makeeachdaycount
RFID是Radio Frequency Identification的縮寫
RFID系統由感應器(Reader)和RFID標籤(Tag)所組成,利用感應器發
射無線電波,觸動感應範圍內的RFID標籤,藉由電磁感應產生電流,
供應RFID標籤上的晶片運作並發出電磁波回應感應器
RFID標籤可分為主動式及被動式
被動式標籤本身沒有電池裝置,所需電流全靠感應器的無線電波電磁感應
產生,所以只有在接收到感應器發出的訊號才會被動的回應感應器
主動式的標籤內置有電池,可以主動傳送訊號供感應器讀取,訊號傳送範
圍也較廣
RFID系統
71
73. Makeeachdaycount
9接Reset (RST),10接Slave select (SS),11接Master-out slave-in
(MOSI),12接Master-in slave-out (MISO),13接Serial Clock (SCK)
Arduino Uno接線
73
Arduino Uno
pin 10
pin 13
pin 11
pin 12
GND
pin9
3.3V
76. Makeeachdaycount
參考程式
#include <SPI.h>
#include <MFRC522.h>
#define SS_PIN 10
#define RST_PIN 9
MFRC522 mfrc522(SS_PIN, RST_PIN); //建構MFRC522物件
void setup() {
Serial.begin(9600);
SPI.begin(); //初始化SPI bus
mfrc522.PCD_Init(); //初始化MFRC522
Serial.println("Scan PICC to see UID and type...");
}
Lab 讀取RFID卡片資料 1/3
76
77. Makeeachdaycount
void loop() {
//確認是否有新卡片
if (mfrc522.PICC_IsNewCardPresent() && mfrc522.PICC_ReadCardSerial()) {
byte *id = mfrc522.uid.uidByte; //取得卡片的UID
byte idSize = mfrc522.uid.size; //取得UID的⻑度
Serial.print("PICC type: "); //顯示卡片類型
MFRC522::PICC_Type piccType = mfrc522.PICC_GetType(mfrc522.uid.sak);
Serial.println(mfrc522.PICC_GetTypeName(piccType));
Serial.print("UID: "); //顯示卡片的UID
for (byte i = 0; i < idSize; i++) {
Serial.print(id[i], HEX); //以16進位顯示UID值
Serial.print(" ");
}
Serial.println();
mfrc522.PICC_HaltA(); //讓卡片進入停止模式
}
}
Lab 讀取RFID卡片資料 2/3
77
81. Makeeachdaycount
參考程式
#include <SPI.h>
#include <MFRC522.h>
#include <Servo.h>
#define SS_PIN 10
#define RST_PIN 9
#define LED_ALARM 2
#define LED_UNLOCK 3
#define SERVO 5
MFRC522 mfrc522(SS_PIN, RST_PIN); //建立MFRC522物件
Servo servo; //建立Servo物件,模擬開關的切換狀態
int cards[][4] = {{0xA3,0x3E,0x82,0xCB}, {0xD0,0xF3,0xBD,0x4E}};
bool access = false;
bool lockerSwitch = true; //開關狀態,預設為「關」
Lab RFID門禁控制 2/5
81
82. Makeeachdaycount
void locker(bool lock) {
if (lock) servo.write(90); //關鎖
else servo.write(10); //開鎖
delay(15); //等伺服馬達轉到定位
}
void reset(){
digitalWrite(LED_UNLOCK, LOW);
digitalWrite(LED_ALARM, LOW);
lockerSwitch = true;
locker(lockerSwitch);
}
Lab RFID門禁控制 3/5
82
84. Makeeachdaycount
void loop() {
if (mfrc522.PICC_IsNewCardPresent() && mfrc522.PICC_ReadCardSerial()) {
byte *id = mfrc522.uid.uidByte; //取得卡片的UID
byte idSize = mfrc522.uid.size; //取得UID的⻑度
for (byte i = 0; i < idSize; i++) {
Serial.print(id[i], HEX); //以16進位顯示UID值
Serial.print(" ");
}
Serial.println();
for(int x = 0; x < sizeof(cards); x++) {
access = true;
for(int i = 0; i < idSize; i++ ) {
if(id[i] != cards[x][i]) { //卡片錯誤,繼續比對下⼀張
access = false;
break;
}
}
if(access) break; //找到正確卡片,結束比對
}
Lab RFID門禁控制 5/5
84