通过红外线发送到Arduino
我需要用Arduino发射红外信号来运行三星电视 我尝试了以下代码:通过红外线发送到Arduino,arduino,infrared,Arduino,Infrared,我需要用Arduino发射红外信号来运行三星电视 我尝试了以下代码: // Lucas Eckels // Http://lucaseckels.com // IR remote control emitter for NEC protocol remote, as described at // Http://www.sbprojects.com/knowledge/ir/nec.htm // Tested on a Samsung LCD TV. #include <util/de
// Lucas Eckels
// Http://lucaseckels.com
// IR remote control emitter for NEC protocol remote, as described at
// Http://www.sbprojects.com/knowledge/ir/nec.htm
// Tested on a Samsung LCD TV.
#include <util/delay.h>
#define IR_PIN 13
// With CONTINOUS defined, the first command is repeated continuously until
// You reset the Arduino. Otherwise, it sends the code once, then waits for
// Another command.
#define CONTINUOUS
// Times are in microseconds
#define ON_START_TIME 4500
#define OFF_START_TIME 4500
#define ON_TIME 580
#define OFF_TIME_ONE 1670
#define OFF_TIME_ZERO 540
#define DEVICE_1 7
#define DEVICE_2 7
void setup() {
pinMode (IR_PIN, OUTPUT);
digitalWrite(IR_PIN, LOW);
Serial.begin(9600);
delay(1000);
Serial.write("Starting up..\n");
}
byte command = 0;
int commandCount = 0;
bool commandReady = false;
void loop() {
if (commandReady) {
Serial.print("Writing command");
Serial.print(command, DEC);
Serial.print("\n");
writeStart();
// Writing device code
writeByte(DEVICE_1);
writeByte(DEVICE_2);
// Writing command code
writeByte(command);
writeByte(~command);
writeEnd();
delay(100);
#ifndef CONTINUOUS
commandReady = false;
command = 0;
commandCount = 0;
#endif
return;
}
if (Serial.available () > 0) {
// Read in a 3-digit decimal command code.
byte incoming = Serial.read();
if (incoming <= '9 ' || incoming >= '0') {
command *= 10;
command += incoming - '0 ';
++commandCount;
}
if (commandCount == 3) {
commandReady = true;
}
}
}
void writeStart() {
modulate(ON_START_TIME);
delayMicroseconds(OFF_START_TIME);
}
void writeEnd() {
modulate(ON_TIME);
}
void writeByte(byte val) {
// Starting with the LSB, write out the
for (int i = 0x01; i & 0xFF; i <<= 1) {
modulate(ON_TIME);
if (val & i) {
delayMicroseconds (OFF_TIME_ONE);
} else {
delayMicroseconds (OFF_TIME_ZERO);
}
}
}
void modulate(int time) {
int count = time / 26;
byte portb = PORTB;
byte portbHigh = portb | 0x20; // Pin 13 is controlled by 0x20 on PORTB.
byte portbLow = portb & ~0x20;
for (int i = 0; i <= count; i++) {
// The ideal version of this loop would be:
// DigitalWrite(IR_PIN, HIGH);
// DelayMicroseconds(13);
// DigitalWrite(IR_PIN, LOW);
// DelayMicroseconds(13);
// But I had a hard time getting the timing to work right. This approach was found
// Through experimentation.
PORTB = portbHigh;
_delay_loop_1(64);
PORTB = portbLow;
_delay_loop_1(64);
}
PORTB = portb;
}
卢卡斯·埃克斯
//Http://lucaseckels.com
//NEC协议远程红外遥控发射器,如中所述
//Http://www.sbprojects.com/knowledge/ir/nec.htm
//在三星液晶电视上测试。
#包括
#定义IR_引脚13
//定义continuous后,第一个命令将连续重复,直到
//你重置了Arduino。否则,它只发送一次代码,然后等待
//另一个命令。
#定义连续的
//时间以微秒为单位
#定义启动时间4500
#定义关闭开始时间4500
#定义时间580
#定义一次关闭时间1670
#定义关闭时间为0 540
#定义设备\u 1 7
#定义设备\u 2 7
无效设置(){
引脚模式(IR_引脚,输出);
数字写入(IR_引脚,低电平);
Serial.begin(9600);
延迟(1000);
Serial.write(“启动..\n”);
}
字节命令=0;
int commandCount=0;
bool commandReady=false;
void循环(){
if(commandReady){
串行打印(“写入命令”);
串行打印(命令,DEC);
串行打印(“\n”);
writeStart();
//写入设备代码
写字节(设备_1);
写字节(设备_2);
//编写命令代码
writeByte(命令);
writeByte(~command);
writeEnd();
延迟(100);
#ifndef连续
commandReady=false;
命令=0;
commandCount=0;
#恩迪夫
返回;
}
如果(Serial.available()>0){
//读入3位十进制命令代码。
字节传入=串行.read();
如果(传入='0'){
命令*=10;
命令+=传入-'0';
++命令计数;
}
if(commandCount==3){
commandReady=true;
}
}
}
void writeStart(){
调制(启动时间);
延迟微秒(关闭/启动时间);
}
无效写入(){
调制(接通时间);
}
无效写字节(字节val){
//从LSB开始,写出
对于(int i=0x01;i&0xFF;iDelayMicroseconds)是相当精确的,并且对于您的任务来说足够精确。但是,您不使用DigitalWrite是正确的。与直接端口分配(PORTB=…)相比,完成此任务所需的时钟周期约为50倍这只需要一个。你只能用这种方式计时一个38MHz的脉冲。我不知道你的延迟环路1有什么作用,但其他一切似乎都很好。(除了“I++”,但我想这是一个剪切粘贴错误)
你检查过它是否真的亮了吗?一部手机或便宜的数码相机会在屏幕上显示IR。我写这篇文章是为了控制LG电视和索尼放大器。你只需要将自己的原始代码保存到头文件中,然后就可以开始了: 我还建议大家阅读一下Ladyada的精彩教程:
我觉得“i++”很可疑——也许“i++”会更好?你的代码中有大量错误,所以我对它们进行了编辑和修复,以使其至少能够正确编译。但我并没有说我添加了任何实际能使其按预期工作的内容。请参阅我的答案。@orenberkovich是否有任何帮助?
// This procedure sends a 38KHz pulse to the IRledPin
// for a certain # of microseconds. We'll use this whenever we need to send codes
void pulseIR(long microsecs) {
// we'll count down from the number of microseconds we are told to wait
cli(); // this turns off any background interrupts
while (microsecs > 0) {
// 38 kHz is about 13 microseconds high and 13 microseconds low
digitalWrite(IRledPin, HIGH); // this takes about 3 microseconds to happen
delayMicroseconds(10); // hang out for 10 microseconds
digitalWrite(IRledPin, LOW); // this also takes about 3 microseconds
delayMicroseconds(10); // hang out for 10 microseconds
// so 26 microseconds altogether
microsecs -= 26;
}
sei(); // this turns them back on
}