|
之前的红外遥控制作都是使用别人的代码或程序库完全。其中Ken Shirriff 的Arduino红外程序库,更是许多Arduino发烧友使用之设计红外制作。
不过这个适合不同红外协议的Ken Shirriff红外程序库並不适合用在Digispark,因为代码复杂,工作繁重,根本不能置入Digispark。没有办法之下唯有自行研究。
由于不熟悉红外原理,花费了一些时间在网站浏览资料,同时一面阅读资料一面测试,终于大功告成。
了觧一下Digispark自带的红外例子
Digispark自带了一个infrared例子,却没有对红外协议分析,按下任何遥控器按钮,只能触发同一事件。以下例子按下任何按钮,都会点亮LED,一秒后关灯。 - int irPin=2; //digital 2 (ATTINT85 pin 7)
- int ledPin=0; //digital 0 (ATTINY85 pin 5)
- void setup()
- {
- pinMode(irPin,INPUT);
- pinMode(ledPin,OUTPUT);
- digitalWrite(0,HIGH);
- }
- void loop()
- {
- if(pulseIn(irPin,LOW)) //reads a pulse on a pin
- {
- //button pressed
- delay(100);
- digitalWrite(ledPin,HIGH);
- delay(1000);
- digitalWrite(ledPin,LOW);
- }
- }
复制代码
代码运用了pulseIn来侦察红外信号。pulseIn是用来侦察谋个引脚的脉冲升高或降低,以便测量其长度,而长度则以微秒(microseconds)计算。
根据以上代码(Sketch),我设计了以下线路图。
下面例子使用Arduino(不是Digispark)作红外解码,毎一个脉冲的长度将从串行监控器(Serial monitor)显示在屏幕上
- int irPin = 2; //IR detector connected to digital 2
- const byte BIT_PER_BLOCK = 32;
- void setup() {
- pinMode(irPin, INPUT);
- Serial.begin(9600);
- }
- void loop() {
- int data[BIT_PER_BLOCK];
- int i;
- for(i = 0 ; i < BIT_PER_BLOCK ; i++) {
- //Start measuring bits, I only want high pulses
- //you may want to use LOW pulse --> pulseIn(irPin, LOW)
- data[i] = pulseIn(irPin, HIGH);
- }
- delay(100);
- for(i = 0 ; i < BIT_PER_BLOCK ; i++) {
- Serial.println(data[i]);
- }
- Serial.println("=========");
- }
复制代码
以下是我的红外数据採样
更完整的数据採样
当然你也可以使用Digispark,将获取的红外资料,通过模拟键盘发送数据至电脑,同时打开文本编辑器(如Windows Notepad)来查看数据,但是此方式的显示速度要比使用串行监视慢许多。
- #include "DigiKeyboard.h"
- int irPin = 2; //IR receiver wired to digital 2 (ATTINY pin7)
- const byte BIT_PER_BLOCK = 32;
- void setup() {
- pinMode(irPin, INPUT);
- Serial.begin(9600);
- }
- void loop() {
- int data[BIT_PER_BLOCK];
- int i;
- // this is generally not necessary but with some older systems it seems to
- // prevent missing the first character after a delay:
- DigiKeyboard.sendKeyStroke(0);
- for(i = 0 ; i < BIT_PER_BLOCK ; i++) {
- //Start measuring bits, I only want high pulses
- //you may want to use LOW pulse --> pulseIn(irPin, LOW)
- data[i] = pulseIn(irPin, HIGH);
- }
- delay(100);
- for(i = 0 ; i < BIT_PER_BLOCK ; i++) {
- DigiKeyboard.println(data[i]);
- }
- DigiKeyboard.println("=========");
- }
复制代码
这里发放完整且可以运行的源代码(针对NEC协议),如想要知道如何工作及分析其他的红外协议,去浏览我的个人网站吧!
以下代码把处理了的NEC红外信号,转换成整数(decimal),通过模拟键盘发送数据至电脑,从而显示各按钮的值。- #include "DigiKeyboard.h"
- int irPin = 2; //Sensor pin connect to digital pin2 (ATINY85 pin7)
- int start_bit = 2200; //Start bit threshold (Microseconds)
- int bin_1 = 1000; //Binary 1 threshold (Microseconds)
- int bin_0 = 400; //Binary 0 threshold (Microseconds)
- const byte BIT_PER_BLOCK = 32;
- void setup() {
- pinMode(irPin, INPUT);
- }
- void loop() {
- DigiKeyboard.update(); //keep on updating the keyboard
- // this is generally not necessary but with some older systems it seems to
- // prevent missing the first character after a delay:
- DigiKeyboard.sendKeyStroke(0);
- int key = getIRKey(); //Fetch the key
- if(key != 0) //Ignore keys that are zero
- {
- DigiKeyboard.print("=>"); //uncomment this if you want to
- DigiKeyboard.println(key); //print out the value of the button
- }
- }
- /////////////////////////////////////////////////////////////
- // decode infrared signal
- /////////////////////////////////////////////////////////////
- int getIRKey() {
- int data[BIT_PER_BLOCK];
- int i;
- while(pulseIn(irPin, HIGH) < start_bit); //Wait for a start bit
- for(i = 0 ; i < BIT_PER_BLOCK ; i++)
- data[i] = pulseIn(irPin, HIGH); //Start measuring bits, I only want HIGH pulses
- delay(100);
- for(i = 0 ; i < BIT_PER_BLOCK ; i++) //Parse them
- {
- if(data[i] > bin_1) //is it a 1?
- data[i] = 1;
- else if(data[i] > bin_0) //is it a 0?
- data[i] = 0;
- else
- return -1; //Flag the data as invalid; Return -1 on invalid data
- }
- //based on NEC protocol, command data started from bit 16
- //and end with bit 24 (8 bits long)
- int result = 0;
- for(i = 16 ; i < 24; i++) {
- DigiKeyboard.print(data[i]); //print out the value of button in binary form
- if(data[i] == 1) result |= (1<<i-16); convert="" data="" bits="" to="" integer
- }
- return result; //Return key number
- }
复制代码
以下代码用于遥控电脑。我用来遥控点唱。此代码占用了4408 Byte Flash Memory,可以使用的Flash Memory剩下1604 Byte 。 - #include "DigiKeyboard.h"
- // not all keys are mapped in the DigiKeyboard.h file.
- // you have to map it here
- #define KEY_HOME 0x4A
- #define KEY_PAGE_UP 0x4B
- #define KEY_PAGE_DOWN 0x4E
- #define KEY_ESCAPE 0x29
- #define KEY_UP_ARROW 0x52
- #define KEY_DOWN_ARROW 0x51
- #define KEY_LEFT_ARROW 0x50
- #define KEY_RIGHT_ARROW 0x4F
- int irPin = 2; //Sensor pin connect to digital pin2 (ATINY85 pin7)
- int start_bit = 2200; //Start bit threshold (Microseconds)
- int bin_1 = 1000; //Binary 1 threshold (Microseconds)
- int bin_0 = 400; //Binary 0 threshold (Microseconds)
- const byte BIT_PER_BLOCK = 32;
- void setup() {
- pinMode(irPin, INPUT);
- }
- void loop() {
- DigiKeyboard.update(); // keep updating the keyboard
- // this is generally not necessary but with some older systems it seems to
- // prevent missing the first character after a delay:
- DigiKeyboard.sendKeyStroke(0);
- int key = getIRKey(); //Fetch the key
- if(key != 0) //Ignore keys that are zero
- {
- //DigiKeyboard.print("=>"); //uncomment this if you want to
- //DigiKeyboard.println(key); //print out the value of the button
- switch(key)
- {
- case 78: DigiKeyboard.println("1"); break;
- case 74: DigiKeyboard.println("2"); break;
- case 70: DigiKeyboard.println("3"); break;
- case 77: DigiKeyboard.println("4"); break;
- case 73: DigiKeyboard.println("5"); break;
- case 69: DigiKeyboard.println("6"); break;
- case 76: DigiKeyboard.println("7"); break;
- case 72: DigiKeyboard.println("8"); break;
- case 68: DigiKeyboard.println("9"); break;
- case 12: DigiKeyboard.println("0"); break;
- case 15: DigiKeyboard.sendKeyStroke(KEY_SPACE); break;
- case 6: DigiKeyboard.sendKeyStroke(KEY_ENTER); break;
- case 4: DigiKeyboard.sendKeyStroke(KEY_ESCAPE); break;
- case 81: DigiKeyboard.sendKeyStroke(KEY_HOME); break;
- case 14: DigiKeyboard.sendKeyStroke(KEY_LEFT_ARROW); break;
- case 10: DigiKeyboard.sendKeyStroke(KEY_RIGHT_ARROW); break;
- case 11: DigiKeyboard.sendKeyStroke(KEY_DOWN_ARROW); break;
- case 7: DigiKeyboard.sendKeyStroke(KEY_UP_ARROW); break;
- }
- }
- }
- /////////////////////////////////////////////////////////////
- // decode infrared signal
- /////////////////////////////////////////////////////////////
- int getIRKey() {
- int data[BIT_PER_BLOCK];
- int i;
- while(pulseIn(irPin, HIGH) < start_bit); //Wait for a start bit
- for(i = 0 ; i < BIT_PER_BLOCK ; i++)
- data[i] = pulseIn(irPin, HIGH); //Start measuring bits, I only want HIGH pulses
- delay(100);
- for(i = 0 ; i < BIT_PER_BLOCK ; i++) //Parse them
- {
- if(data[i] > bin_1) //is it a 1?
- data[i] = 1;
- else if(data[i] > bin_0) //is it a 0?
- data[i] = 0;
- else
- return -1; //Flag the data as invalid; Return -1 on invalid data
- }
- //based on NEC protocol, command data started from bit 16
- //and end with bit 24 (8 bits long)
- int result = 0;
- for(i = 16 ; i < 24; i++) {
- //DigiKeyboard.print(data[i]); //print out the value of button in binary form
- if(data[i] == 1) result |= (1<<i-16); convert="" data="" bits="" to="" integer
- }
- return result; //Return key number
- }
复制代码
最後一个是4路红外遥控
使用相同的红外遥控器来控制4个LED,按下各自按键将会切换各自相关LED。完成代码(Sketch)上载后 ,你可以除去1.5K电阻,两个68ohm电阻和两个Zener二极管。
此代码占用了1682Byte Flash Memory,可以使用的Flash Memory剩下4330 Byte
- int irPin = 2; //Sensor pin connect to digital pin2 (ATINY85 pin7)
- int led1 = 0; //led connect to digital pin0 (ATTINY85 pin5)
- int led2 = 1; //led connect to digital pin1 (ATTINY85 pin6)
- int led3 = 3; //led connect to digital pin3 (ATTINY85 pin2)
- int led4 = 4; //led connect to digital pin4 (ATTINY85 pin3)
- int start_bit = 2200; //Start bit threshold (Microseconds)
- int bin_1 = 1000; //Binary 1 threshold (Microseconds)
- int bin_0 = 400; //Binary 0 threshold (Microseconds)
- const byte BIT_PER_BLOCK = 32;
- void setup() {
- pinMode(irPin, INPUT);
- pinMode(led1, OUTPUT);
- pinMode(led2, OUTPUT);
- pinMode(led3, OUTPUT);
- pinMode(led4, OUTPUT);
- digitalWrite(led1, LOW); //turn off LED
- digitalWrite(led2, LOW);
- digitalWrite(led3, LOW);
- digitalWrite(led4, LOW);
- }
- void loop() {
- int key = getIRKey(); //Fetch the key
- if(key != 0) //Ignore keys that are zero
- {
- switch(key)
- {
- case 78: toggleLED(led1); break;
- case 74: toggleLED(led2); break;
- case 70: toggleLED(led3); break;
- case 77: toggleLED(led4); break;
- }
- }
- }
- /////////////////////////////////////////////////////////////
- // toggle led
- /////////////////////////////////////////////////////////////
- void toggleLED(byte ledPin) {
- if(digitalRead(ledPin) != 1) //This toggles the led
- digitalWrite(ledPin, HIGH);
- else
- digitalWrite(ledPin, LOW);
- }
- /////////////////////////////////////////////////////////////
- // decode infrared signal
- /////////////////////////////////////////////////////////////
- int getIRKey() {
- int data[BIT_PER_BLOCK];
- int i;
- while(pulseIn(irPin, HIGH) < start_bit); //Wait for a start bit
- for(i = 0 ; i < BIT_PER_BLOCK ; i++)
- data[i] = pulseIn(irPin, HIGH); //Start measuring bits, I only want HIGH pulses
- delay(100);
- for(i = 0 ; i < BIT_PER_BLOCK ; i++) //Parse them
- {
- if(data[i] > bin_1) //is it a 1?
- data[i] = 1;
- else if(data[i] > bin_0) //is it a 0?
- data[i] = 0;
- else
- return -1; //Flag the data as invalid; Return -1 on invalid data
- }
- //based on NEC protocol, command data started from bit 16
- //and end with bit 24 (8 bits long)
- int result = 0;
- for(i = 16 ; i < 24; i++) {
- if(data[i] == 1) result |= (1<<i-16); convert="" data="" bits="" to="" integer
- }
- return result; //Return key number
- }
复制代码
注:
如果你是根据我的方式自制Digispark,由于使用了以下熔丝位,只能拥有五个IO,重置(Reset)不能当着IO。
- Extended: 0xFE
- High: 0xDD
- Low: 0xE1
建议重置(Reset)引脚与Vcc(+5V)之间连接一个1K至10K的电阻器以防止电平漂动。而造成电路不稳定。
|
本帖子中包含更多资源
您需要 登录 才可以下载或查看,没有帐号?注册
x
|