Digispark红外接收器
之前的红外遥控制作都是使用别人的代码或程序库完全。其中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;
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 = pulseIn(irPin, HIGH);
}
delay(100);
for(i = 0 ; i < BIT_PER_BLOCK ; i++) {
Serial.println(data);
}
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;
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 = pulseIn(irPin, HIGH);
}
delay(100);
for(i = 0 ; i < BIT_PER_BLOCK ; i++) {
DigiKeyboard.println(data);
}
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;
int i;
while(pulseIn(irPin, HIGH) < start_bit); //Wait for a start bit
for(i = 0 ; i < BIT_PER_BLOCK ; i++)
data = 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 > bin_1) //is it a 1?
data = 1;
else if(data > bin_0) //is it a 0?
data = 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); //print out the value of button in binary form
if(data == 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;
case6: DigiKeyboard.sendKeyStroke(KEY_ENTER); break;
case4: 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;
case7: DigiKeyboard.sendKeyStroke(KEY_UP_ARROW); break;
}
}
}
/////////////////////////////////////////////////////////////
// decode infrared signal
/////////////////////////////////////////////////////////////
int getIRKey() {
int data;
int i;
while(pulseIn(irPin, HIGH) < start_bit); //Wait for a start bit
for(i = 0 ; i < BIT_PER_BLOCK ; i++)
data = 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 > bin_1) //is it a 1?
data = 1;
else if(data > bin_0) //is it a 0?
data = 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); //print out the value of button in binary form
if(data == 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)
{
case78: toggleLED(led1); break;
case74: toggleLED(led2); break;
case70: toggleLED(led3); break;
case77: 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;
int i;
while(pulseIn(irPin, HIGH) < start_bit); //Wait for a start bit
for(i = 0 ; i < BIT_PER_BLOCK ; i++)
data = 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 > bin_1) //is it a 1?
data = 1;
else if(data > bin_0) //is it a 0?
data = 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 == 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的电阻器以防止电平漂动。而造成电路不稳定。
最近玩了下Digispark,挺强大的,我觉得连着电脑特别好玩,带USB,不用串口,谢谢你的分享 smfox10 发表于 2013-6-1 21:00 static/image/common/back.gif
最近玩了下Digispark,挺强大的,我觉得连着电脑特别好玩,带USB,不用串口,谢谢你的分享
之前喜欢玩这个最简单又最便宜的Arduino,基本上已经放弃了。现在玩Digispark。
来吧!一起研究Digispark吧。
页:
[1]