认识红外线
可见光、红外线和电波都是一种电磁波, 远红外线和近红外线在室温下释放的红外波长约为10um(微米)。靠近可见光的近红外线几乎不会散发热能,通常用于红外通信、遥控和距离传感器。
人体红外传感器
传感器上部的白色半透明PE透镜粘在电路板上,有一个热释电传感器(pyroelectric)代表该模块随温度变化产生电子信号。在传感器模块上IC电路将以高电位或低电位的形式接收和处理传感器信号。人体红外检测模块相当于电子开关,通常输出低电位(0V),当检测到人体移动时,它变成高电位(3.3V)。 传感器全名,红外线(Infrared)英文简称IR,所以这个传感器也叫PIR移动传感器通常被称为人体红外传感器。所谓的被动检测意味着该传感器不同于超声波传感器。它不会发出检测信号,而是被动地接收红外源。传感器内部有两个检测窗口,被检测物体必须水平移动,才能比较红外线的变化。如果向前移动,就不容易检测到。 热释电传感器(pyroelectric)代表该模块随温度变化产生电子信号。传感器模块IC电路将以高电位或低电位的形式接收和处理传感器信号。简而言之,人体红外检测模块相当于电子开关,通常输出低电位(0V),当检测到人体移动时,它变成高电位(3.3V)。
动手做12-1 监测人体运动
使用人体红外传感器点亮位置Arduino板子13端口的LED **程序:**因为人体红外传感器模块只会返回0和1两个状态值。
const byte pirPin = 12; ////红外传感器信号端口 const byte ledPin = 13; //LED端口 void setup() { pinMode(pirPin, INPUT); pinMode(ledPin, OUTPUT); //LED端口设置为输出 } void loop(){ boolean val = digitalRead(pirPin); ///读取传感器值 if (val) { digitalWrite(ledPin, HIGH); } else { digitalWrite(ledPin, LOW); } }
红外线遥控
红外遥控接收器只有特定的频率信号(正确的名称叫载波,通常是36kHZ或38kHZ)与通关密语有反应。这个通关密语叫协议。
红外遥控接收元件
红外遥控接收元件包括红外接收元件和信号处理IC,一般型号是TSOP4836和TSOP4838(后两个数字代表载波频率)。 普通红外接收元件不含信号处理IC,其主要规格是红外波长范围。 红外接收元件的外观一般LED,通常用于障碍物检测和距离感测,
动手做12-2 使用IRremote扩展库分析红外遥控值
将组装一个Arduino通过万用红外遥控接收器Ken Shirriff写的IRremote扩展库(网站:https://github.com/shirriff/Arduino-IRremote),读取各大品牌的红外遥控信号。 请先把“IRremote复制扩展库文件Arduino的libraries文件夹→→→IRrecvDemo。
#include <IRremote.h> int RECV_PIN = 11; IRrecv irrecv(RECV_PIN); ///声明红外接收对象的名称irrecv,接收端口是11 decode_results results; // 声明存储接收值的变量 void setup() { Serial.begin(9600); irrecv.enableIRIn(); ///启动红外接收功能 } void loop() { //分析红外接收值,若decode()返回true,收到新数据的代表。 if (irrecv.decode(&results)) { Serial.println(results.value, HEX); //读取分析后的数字,并以16进位格式输出。 irrecv.resume(); //准备接收下一组数据 } }
阅读原始的红外线(raw)格式
IRremote扩展库提供另一个IRrecvDump”示例程序,能辨别并显示红外线遥控信号的格式名称,并输出接收器所收到的原始数据。
//------------------------------------------------------------------------------ // Include the IRremote library header // #include <IRremote.h> //------------------------------------------------------------------------------ // Tell IRremote which Arduino pin is connected to the IR Receiver (TSOP4838) // int recvPin = 11; IRrecv irrecv(recvPin); // ============================================================================= // Configure the Arduino // void setup ( ) { Serial.begin(9600); // Status message will be sent to PC at 9600 baud irrecv.enableIRIn(); // Start the receiver } // ============================================================================= // Display IR code // void ircode (decode_results *results) { // Panasonic has an Address if (results->decode_type == PANASONIC) { Serial.print(results->address, HEX); Serial.print(":"); } // Print Code Serial.print(results->value, HEX); } // ============================================================================= // Display encoding type // void encoding (decode_results *results) { switch (results->decode_type) { default: case UNKNOWN: Serial.print("UNKNOWN"); break ; case NEC: Serial.print("NEC"); break ; case SONY: Serial.print("SONY"); break ; case RC5: Serial.print("RC5"); break ; case RC6: Serial.print("RC6"); break ; case DISH: Serial.print("DISH"); break ; case SHARP: Serial.print("SHARP"); break ; case JVC: Serial.print("JVC"); break ; case SANYO: Serial.print("SANYO"); break ; case MITSUBISHI: Serial.print("MITSUBISHI"); break ; case SAMSUNG: Serial.print("SAMSUNG"); break ; case LG: Serial.print("LG"); break ; case WHYNTER: Serial.print("WHYNTER"); break ; case AIWA_RC_T501: Serial.print("AIWA_RC_T501"); break ; case PANASONIC: Serial.print("PANASONIC"); break ; case DENON: Serial.print("Denon"); break
}
}
//+=============================================================================
// Dump out the decode_results structure.
//
void dumpInfo (decode_results *results)
{
// Check if the buffer overflowed
if (results->overflow) {
Serial.println("IR code too long. Edit IRremoteInt.h and increase RAWBUF");
return;
}
// Show Encoding standard
Serial.print("Encoding : ");
encoding(results);
Serial.println("");
// Show Code & length
Serial.print("Code : ");
ircode(results);
Serial.print(" (");
Serial.print(results->bits, DEC);
Serial.println(" bits)");
}
//+=============================================================================
// Dump out the decode_results structure.
//
void dumpRaw (decode_results *results)
{
// Print Raw data
Serial.print("Timing[");
Serial.print(results->rawlen-1, DEC);
Serial.println("]: ");
for (int i = 1; i < results->rawlen; i++) {
unsigned long x = results->rawbuf[i] * USECPERTICK;
if (!(i & 1)) { // even
Serial.print("-");
if (x < 1000) Serial.print(" ") ;
if (x < 100) Serial.print(" ") ;
Serial.print(x, DEC);
} else { // odd
Serial.print(" ");
Serial.print("+");
if (x < 1000) Serial.print(" ") ;
if (x < 100) Serial.print(" ") ;
Serial.print(x, DEC);
if (i < results->rawlen-1) Serial.print(", "); //',' not needed for last one
}
if (!(i % 8)) Serial.println("");
}
Serial.println(""); // Newline
}
//+=============================================================================
// Dump out the decode_results structure.
//
void dumpCode (decode_results *results)
{
// Start declaration
Serial.print("unsigned int "); // variable type
Serial.print("rawData["); // array name
Serial.print(results->rawlen - 1, DEC); // array size
Serial.print("] = {"); // Start declaration
// Dump data
for (int i = 1; i < results->rawlen; i++) {
Serial.print(results->rawbuf[i] * USECPERTICK, DEC);
if ( i < results->rawlen-1 ) Serial.print(","); // ',' not needed on last one
if (!(i & 1)) Serial.print(" ");
}
// End declaration
Serial.print("};"); //
// Comment
Serial.print(" // ");
encoding(results);
Serial.print(" ");
ircode(results);
// Newline
Serial.println("");
// Now dump "known" codes
if (results->decode_type != UNKNOWN) {
// Some protocols have an address
if (results->decode_type == PANASONIC) {
Serial.print("unsigned int addr = 0x");
Serial.print(results->address, HEX);
Serial.println(";");
}
// All protocols have data
Serial.print("unsigned int data = 0x");
Serial.print(results->value, HEX);
Serial.println(";");
}
}
//+=============================================================================
// The repeating section of the code
//
void loop ( )
{
decode_results results; // Somewhere to store the results
if (irrecv.decode(&results)) { // Grab an IR code
dumpInfo(&results); // Output the results
dumpRaw(&results); // Output the results in RAW format
dumpCode(&results); // Output the results as source code
Serial.println(""); // Blank line between entries
irrecv.resume(); // Prepare for the next value
}
}
动手做12-3 使用红外线遥控器控制舵机
实验说明:取得红外线遥控器的句柄之后,你就可以用遥控器来控制Arduino,本例将示范通过红外线遥控舵机。 实验程序:将依据遥控器的左、右箭头键,调整舵机的旋转角度,以及“录像”按键打开或关闭板子上第13脚的LED。
#include <IRremote.h>
#include <Servo.h>
Servo servo;
const byte RECV_PIN = 11; //
const byte LED_PIN = 13; //
const byte SERVO_PIN = 8; //
boolean sw = false; //
byte servoPos = 90; //
IRrecv irrecv(RECV_PIN); //
decode_results results; //
void setup() {
irrecv.enableIRIn(); //
pinMode(LED_PIN, OUTPUT); //
servo.attach(SERVO_PIN); //
servo.write(servoPos); //
}
void loop() {
if (irrecv.decode(&results)) { //
switch (results.value) { //
case 0xC1C7C03F: //若此数值等于“录像”
sw = !sw; //
digitalWrite(LED_PIN, sw); //
break;
case 0xC1C7C43B: //
if (servoPos > 10) { //
servoPos -= 10; //
servo.write(servoPos); //
}
break;
case 0xC1C744BB:
if (servoPos < 170) {
servoPos += 10; //
servo.write(servoPos); //
}
break;
}
irrecv.resume(); //
}
}
动手做12-4 从Arduino发射红外线遥控电器
IRremote扩展库也具备发射红外线遥控信号的功能,本单元将组装一个Arduino红外线遥控发射器,并从“串口监视器”指挥它来遥控家电 根据IRremote扩展库的设定,红外线发射LED必须接在第3端口,而且最好先串联一个330Ω电阻保护LED。 使用IRremote扩张库发射红外线信号之前,必须先声明一个“I”类型的对象IRsend irsend;
,程序将通过此对象发射制定格式的信号,以发出NEC红外线为例,指令:irsend.sendNEC(红外线编码, 位数);
示例: 从串口获得任何字符时,Arduino发射红外线上面的信号;
#include <IRremote.h>
IRsend irsend;
void setup(){
Serial.begin(9600);
}
void loop() {
if (Serial.read() != -1) {
irsend.sendNEC(0xC1C7C03F, 32);
Serial.println("Action!");
}
}