[完结] 关于红外遥控的一点问题

请注意,本文编写于 204 天前,最后修改于 1 天前,其中某些信息可能已经过时。

文章比较长,由于之前写思路比较混乱,现在重新捋一捋,先上个手动目录,点击标题即可跳转,按下屏幕右下角返回顶端,真是方便的不得了呢!妈妈再也不用担心我读文章找不着北了呢!关于后面的求解过程部分不推荐读完,因为有价值的部分在前面讲的差不多了2333 篇幅实在太长了,整的跟老来来的裹 jio 布似的。

 

基本情况

 

设想

我原本的想法很简单,风扇速度是用代表档次的变量 fanspeed 最终控制的,现在在代码中加入 irRemote.h 库支持用来读取红外接收器接收的红外信号 results.value ,红外接收部分电路直接串联到单片机上,跟原来的轻触按键开关控制电路并联。读取信号之后对 fanspeed 进行处理即可实现遥控功能,例如

  • 按键 CH+ 信号在单片机内接收为 16 进制代码 0xFFE21D ,比较 results.value0xFFE21D ,相等则给 fanspeed + 1 ,如果超过 3 则设置为 3 。
  • 按键 CH- 信号在单片机内接收为 16 进制代码 0xFFA25D ,比较 results.value0xFFA25D ,相等则给 fanspeed - 1 ,如果小于 0 则设置为 0 。
  • 按键 0 信号在单片机内接收为 16 进制代码 0xFF6897 ,比较 results.value0xFF6897 ,相等则设置 fanspeed = 0
  • 按键 1 信号在单片机内接收为 16 进制代码 0xFF30CF ,比较 results.value0xFF30CF ,相等则设置 fanspeed = 1
  • 按键 2 信号在单片机内接收为 16 进制代码 0xFF18E7 ,比较 results.value0xFF18E7 ,相等则设置 fanspeed = 2
  • 按键 3 信号在单片机内接收为 16 进制代码 0xFF7A85 ,比较 results.value0xFF7A85 ,相等则设置 fanspeed = 3

 

电路图

红外遥控调速风扇 电路布线
红外遥控调速风扇 电路布线

 

代码

#include <IRremote.h>
 
const int buttonPin = 2;
const int ledPin = 13;
const int irReceiverPin = 11;
const int motorIn1 = 9;
const int motorIn2 = 10;
int fanspeed = 0;
#define rank0 0
#define rank1 150
#define rank2 200
#define rank3 250
int btState;
int lastbtState = LOW;
// the time measured in milisecounds will quickly become a bigger number,
// which can't be stored in an int.
long lastDebounceTime = 0;
long debounceDelay = 50;
IRrecv irrecv(irReceiverPin);
decode_results results;

void setup() {
  lastbtState = LOW;
  pinMode(buttonPin, INPUT);
  pinMode(ledPin, OUTPUT);
  pinMode(motorIn1, OUTPUT);
  pinMode(motorIn2, OUTPUT);
  Serial.begin(9600);
  irrecv.enableIRIn();
}
 
void loop() {
  // read the state of the switch into a local variable:
  int reading = digitalRead(buttonPin);
  // if the button state is different from last time,reset the debouncing timer.
  if (reading != lastbtState) {
    lastDebounceTime = millis();
  }
  // debounce treatment.
  if ((millis() - lastDebounceTime) > debounceDelay) {
    if (reading != btState) {
      // store the state of button in btState.
      btState = reading;
      if (btState == HIGH) {
        // only toggle the LED if the new button state is HIGH.
        digitalWrite(ledPin, HIGH);
        // codes for controlling the fan speed.
        fanspeed = fanspeed + 1;
        if (fanspeed >= 4) {
          fanspeed = 0;
        }
      }
      else
        digitalWrite(ledPin, LOW);
    }
  }
 
  // extra function irReceive() to deal with the signal sent by remotecontroller.
  if (irrecv.decode(&results)) {
    delay(600);
    irrecv.resume();
  }
  // irSignal treatment.
  if (results.value == 0xFF30CF) {
    // set the fanspeed = 1.
    digitalWrite(ledPin, HIGH);
    fanspeed = 1;
    Serial.println("You have pressed the 1 button and set the fanspeed = 1.");
    Serial.print("Detail Information:irCode:");
    Serial.print(results.value, HEX);
    Serial.print(",bits:");
    Serial.println(results.bits);
    Serial.println("A circle is finished");
  }
  if (results.value == 0xFF18E7) {
    // set the fanspeed = 2.
    digitalWrite(ledPin, HIGH);
    fanspeed = 2;
    Serial.println("You have pressed the 2 button and set the fanspeed = 2.");
    Serial.print("Detail Information:irCode:");
    Serial.print(results.value, HEX);
    Serial.print(",bits:");
    Serial.println(results.bits);
    Serial.println("A circle is finished");
  }
  if (results.value == 0xFF7A85) {
    // set the fanspeed = 3.
    digitalWrite(ledPin, HIGH);
    fanspeed = 3;
    Serial.println("You have pressed the 3 button and set the fanspeed = 3.");
    Serial.print("Detail Information:irCode:");
    Serial.print(results.value, HEX);
    Serial.print(",bits:");
    Serial.println(results.bits);
    Serial.println("A circle is finished");
  }
  if (results.value == 0xFFE21D) {
    // set the fanspeed ++.
    digitalWrite(ledPin, HIGH);
    fanspeed = fanspeed + 1;
    if (fanspeed >= 3) {
      fanspeed = 3;
    }
    Serial.println("You have pressed the CH+ button and make the fanspeed + 1.");
    Serial.print("Detail Information:irCode:");
    Serial.print(results.value, HEX);
    Serial.print(",bits:");
    Serial.println(results.bits);
    Serial.println("A circle is finished");
  }
  if (results.value == 0xFFA25D) {
    // set the fanspeed --.
    digitalWrite(ledPin, HIGH);
    fanspeed = fanspeed - 1;
    if (fanspeed <= 0) {
      fanspeed = 0;
    }
    Serial.println("You have pressed the CH- button and make the fanspeed - 1.");
    Serial.print("Detail Information: irCode:");
    Serial.print(results.value, HEX);
    Serial.print(",bits:");
    Serial.println(results.bits);
    Serial.println("A circle is finished");
  }
  else if (results.value == 0xFF6897) {
    // set the fanspeed = 0.
    digitalWrite(ledPin, HIGH);
    fanspeed = 0;
    Serial.println("You have pressed the 0 button and turn off the fan.");
    Serial.print("Detail Information: irCode:");
    Serial.print(results.value, HEX);
    Serial.print(",bits:");
    Serial.println(results.bits);
    Serial.println("A circle is finished");
    delay(400);
  }
 
  switch (fanspeed) {
    case 1: clockwise(rank1);break;
    case 2: clockwise(rank2);break;
    case 3: clockwise(rank3);break;
    default: clockwise(rank0);break;
  }
  lastbtState = reading;
}
 
void clockwise(int Speed) {
  analogWrite(motorIn1, 0);
  analogWrite(motorIn2, Speed);
}

注:为了找到关于红外信号处理的程序运行了哪里,我添加了好几条 Serial.print(); Serial.println(); 来输出提示,我想对程序运行应该没有什么影响。

 

那么问题来了

  • 红外信号接收出错
    表现为 按下一次遥控之后红外信号持续输入 、 接收不到红外信号 等情况。

前一个现象是因为处理完一个红外信号之后系统立刻激活了红外接收,信号在极短的延时(相比按下按键的时间该延时极短)之后立刻传入,设置一定长度延时即可解决。这里补充说明一句,按键长按出现 FFFFFFFF 是正常情况。后一个现象是由于关于红外解码的启动与下一次激活的代码逻辑出错,可能是在 ifelse 的嵌套中混乱了。
此外最重要的一个原因可能是因为 IRremote.h 库引用的定时器与原程序或其他库冲突,即使用了相同的定时器。这个问题可以参考 2019.2.3 0:002019.2.4 1:302019.2.4 14:302019.2.5 15:302019.2.17 00:00 几个部分尝试解决。

  • 干扰轻触按键信号
    不知道是代码的位置问题还是怎么回事,有种情况就是按键需要长按一段时间才能调节,估计是我为了防止红外信号接收重复设置的延时长度 delay(600);

这个问题完全是因为写代码不用心,ifelse 嵌套乱七八糟导致的。

  • 只处理一次红外信号
    就是只执行了一遍红外信号处理的程序,之后所有信号都接收但跳出了我设定的判断条件然后分别执行处理的片段直接返回了 A circle is finished.

这个问题很大一部分是因为语句嵌套有问题,下一次激活红外解码的语句在整个循环中只运行了一次。

以上为测试过程中出现的问题,未必同时出现,代码也只是跟上面提供的代码相近。

在求解过程的最后,我发现红外信号在程序实在找不出问题的情况下还是出错,原因居然是元器件有问题。将原来使用的 J16409 红外接收器意外压到发生了一点形变之后,红外信号接收变得十分灵敏 hhhhh 。所以,我想说的是,有的时候钱真的是万能的,加钱换新能解决很多问题。

重启能解决电脑 90% 的问题,重装系统能解决电脑 99% 的问题,重买一台能将解决电脑 100% 的问题。 ——微博热评

  • 使用 9V 电池无法供电
    连接 9V 电池后电机无法转动, ULN2003 驱动上指示灯正常亮起。我以为是 2019.2.4 10:00 那里那种情况,是单片机底层有什么问题。

实际上只是因为 9V 电池在这里降压严重无法驱动电机导致的,可以使用 5V 输出口的充电宝通过 9V 升压线连接单片机即可完美解决。网商平台搜索 9V 5.5mm 升压线购买即可。

 

最终代码

/*

   Arduino 红外遥控调速风扇
   RGB LED 用来提示用户,风扇转动时呈蓝光,接收到红外信号时呈红光,按键按下时呈绿光。
   轻触开关按键实现从 0~3 档手动依次循环。
   红外信号实现控制风扇档次,档次加减,关闭风扇三个功能。

*/
#include <IRremote.h>
#include <IRremoteInt.h>

const int buttonPin = 2;
const int ledPin = 13;
const int irReceiverPin = 3;
const int RPin = 11;
const int GPin = 5;
const int BPin = 6;
const int motorIn1 = 9;
const int motorIn2 = 10;
int fanspeed = 0;
#define rank0 0
#define rank1 150
#define rank2 200
#define rank3 250
int btState;
int lastbtState = LOW;
long lastDbTime = 0;
long dbDelay = 60000;
IRrecv irrecv(irReceiverPin);
decode_results results;

void setup() {
  pinMode(buttonPin, INPUT);
  pinMode(ledPin, OUTPUT);
  pinMode(motorIn1, OUTPUT);
  pinMode(motorIn2, OUTPUT);
  pinMode(RPin, OUTPUT);
  pinMode(GPin, OUTPUT);
  pinMode(BPin, OUTPUT);
  Serial.begin(9600);
  irrecv.enableIRIn();
  analogWrite(RPin, 0);
  analogWrite(GPin, 0);
  analogWrite(BPin, 0);
}

void loop() {
  int reading = digitalRead(buttonPin);
  if (reading != lastbtState) {
    lastDbTime = micros();
  }
  if ((micros() - lastDbTime) > dbDelay) {
    if (reading != btState) {
      // store the state of button in btState.
      btState = reading;
      if (btState == HIGH) {
        digitalWrite(ledPin, HIGH);
        fanspeed = fanspeed + 1;
        if (fanspeed >= 4) {
          fanspeed = 0;
        }
      }
      else
        digitalWrite(ledPin, LOW);
    }
  }
  // function for dealing with the signal sent by remotecontroller.
  if (irrecv.decode(&results)) {
    irSignalProcess(results.value);
    /* 调试部分代码
    Serial.print("Detail Information: irCode:");
    Serial.print(results.value, HEX);
    Serial.print(",bits:");
    Serial.println(results.bits);
    */
    delay(600);
    analogWrite(RPin, 0);
    /* 调试部分代码
    Serial.println("Delay is end,try to reset the irReceiver.");
    */
    while (!irrecv.isIdle());
    irrecv.resume();
    /* 调试部分代码
    Serial.println("Reset Success!");
    */
    delay(500);
  }

  if (reading == HIGH) {
    analogWrite(GPin, 255);
  }
  else {
    analogWrite(GPin, 0);
  }

  if (fanspeed != 0) {
    analogWrite(BPin, 255);
  }
  else {
    analogWrite(BPin, 0);
  }

  // fan speed is divided into different grades.
  switch (fanspeed) {
    case 1: clockwise(rank1); break;
    case 2: clockwise(rank2); break;
    case 3: clockwise(rank3); break;
    default: clockwise(rank0); break;
  }
  // save the reading and through the loop next time.
  lastbtState = reading;
}
void irSignalProcess(unsigned long value) {
  switch (value) {
    case 0xFF22DD:
      analogWrite(RPin, 255);
      /* 调试部分代码
      Serial.println("Button |<< had been pressed.");
      */
      fanspeed = fanspeed - 1;
      if (fanspeed <= 0) {
        fanspeed = 0;
      }
      /* 调试部分代码
      Serial.println("fanspeed - 1. Finished.");
      */
      break;
    case 0xFF02FD:
      analogWrite(RPin, 255);
      /* 调试部分代码
      Serial.println("Button >>| has been pressed.");
      */
      fanspeed = fanspeed + 1;
      if (fanspeed >= 3) {
        fanspeed = 3;
      }
      /* 调试部分代码
      Serial.println("fanspeed + 1. Finished.");
      */
      break;
    case 0xFF629D:
      analogWrite(RPin, 255);
      /* 调试部分代码
      Serial.println("Button CH has been pressed.");
      */
      fanspeed = 0;
      /* 调试部分代码
      Serial.println("You have turn down the fan.");
      */
      break;
    case 0xFF30CF:
      analogWrite(RPin, 255);
      /* 调试部分代码
      Serial.println("Button 1 has been pressed.");
      */
      fanspeed = 1;
      /* 调试部分代码
      Serial.println("fanspeed = 1. Finished.");
      */
      break;
    case 0xFF18E7:
      analogWrite(RPin, 255);
      /* 调试部分代码
      Serial.println("Button 2 has been pressed.");
      */
      fanspeed = 2;
      /* 调试部分代码
      Serial.println("fanspeed = 2. Finished.");
      */
      break;
    case 0xFF7A85:
      analogWrite(RPin, 255);
      /* 调试部分代码
      Serial.println("Button 3 has been pressed.");
      */
      fanspeed = 3;
      /* 调试部分代码
      Serial.println("fanspeed = 3. Finished.");
      */
      break;
  }
}
void clockwise(int Speed) {
  analogWrite(motorIn1, 0);
  analogWrite(motorIn2, Speed);
}

 

求解过程

 

2019.2.3 0:00

根据某菊苣 WSY 提示,应该是 irrecv.decode 附近的问题。尝试查找资料:

class IRrecv
{
public:
        IRrecv(int recvpin);
        void blink13(int blinkflag);
        int decode(decode_results *results);
        void enableIRIn();
        void resume();
}
class decode_results {
public:
        int decode_type;                // NEC、SONY、RC5、RC6、夏普、松下、JVC、未知
        unsigned int panasonicAddress;  // 仅用于松下格式的解码
        unsigned long value;            // 解码值
        int bits;                       // 解码值的位数
        volatile unsigned int *rawbuf;  // 间隔50微秒“滴答周期”采样的原始协议码
        int rawlen;                     // 在rawbuf中的记录长度
}

 

2019.2.4 1:30

根据上面百度文库的资料,IRremote.h 工作时是这样的:irrecv.enbleIRIn(); 启动红外解码,这时候 IRrecv 对象在后台接收红外线信号,利用 decode() 函数持续检查看有没有解码成功,irrecv.decode(&results) 解码成功会返回 ture 并将解码结果储存于变量 results 中。在解码一个红外信号之后要运行 resume() 函数才会持续接收下一组信号。基本思路是先利用程序解析所使用遥控按键的编码,根据所得到的编码判断是否为某个按键,这个解析出的编码数值为 unsigned long 型。
最终他给出了一个这样的程序(这里只写点逻辑顺序之类的):

# include <IRremote.h>
 
int irReceiverPin = 11;              // 定义红外接收器引脚
IRrecvirrecv(irReciverPin);         // 定义 IRrecv 对象接收 irReciverPin 引脚接收的信号
decode_results results;             // 将解码结果储存于 decode_results 构造的对象 results 中
 
void irSignalProcess(unsign long value)
{
  switch(value)                     // 运用 switch case 语句判断红外信号
  {
    case 0xFFA25D: /* PROCESSING1 */  break;
    case 0xFF629D: /* PROCESSING2 */  break;
    case 0xFF629D: /* PROCESSING3 */  break;
    case 0xFF629D: /* PROCESSING4 */  break;
  }
}
 
void setup()
{
  Serial.begin(9600);
  irrecv.enableIRIn();              // 启动红外解码
}
 
void loop()
{
  if (irrecv.decode(&results))      // 一旦接收到红外信号则运行
  {
    irSignalProcess(results.value); // 执行 setup() 前的红外信号处理函数
    delay(500);                     // 如果不设置延时,红外接收会在按下遥控期间重复接收到信号
    irrecv.resume();                // 类似重置红外接收
  }
}

将这个模型结合到之前给出的代码中,实测遥控成功 (测试也会出现信号读取异常的情况,可能只是当时人品爆发出错较少)的代码如下:

#include <IRremote.h>
 
/* 原头部定义引脚以及变量代码,这里省略以缩短篇幅 */
 
const int irReceiverPin = 7;
IRrecv irrecv(irReceiverPin);
decode_results results;
 
void irSignalProcess(unsigned long value) {
  switch (value) {
    case 0xFF22DD:
      Serial.println("Button |<< had been pressed.");
      fanspeed = fanspeed - 1;
      if (fanspeed <= 0) {
        fanspeed = 0;
      }
      Serial.println("fanspeed - 1. Finished.");
      break;
    case 0xFF02FD:
      Serial.println("Button >>| has been pressed.");
      fanspeed = fanspeed + 1;
      if (fanspeed >= 3) {
        fanspeed = 3;
      }
      Serial.println("fanspeed + 1. Finished.");
      break;
    case 0xFF629D:
      Serial.println("Button CH has been pressed.");
      fanspeed = 0;
      Serial.println("You have turn down the fan.");
      break;
    case 0xFF30CF:
      Serial.println("Button 1 has been pressed.");
      fanspeed = 1;
      Serial.println("fanspeed = 1. Finished.");
      break;
    case 0xFF18E7:
      Serial.println("Button 2 has been pressed.");
      fanspeed = 2;
      Serial.println("fanspeed = 2. Finished.");
      break;
    case 0xFF7A85:
      Serial.println("Button 3 has been pressed.");
      fanspeed = 3;
      Serial.println("fanspeed = 3. Finished.");
      break;
  }
}
 
void setup() {
   
  /* 原定义引脚输入输出代码,这里省略以缩短篇幅 */
   
  Serial.begin(9600);
  irrecv.enableIRIn();
}
 
void loop() {
   
  /* 原轻触开关按键模块代码,这里省略以缩短篇幅 */
   
  // dealing with the signal sent by remotecontroller.
  if (irrecv.decode(&results)) {
    irSignalProcess(results.value);
    /* 这里可以用来调试接受红外信号的信息
    Serial.print("Detail Information: irCode:");
    Serial.print(results.value, HEX);
    Serial.print(",bits:");
    Serial.println(results.bits);
    */
    delay(500);
    irrecv.resume();
  }
   
  /* 原风扇档次 switch case 语句和 loop() 函数后半部分代码,这里省略以缩短篇幅 */
   
}
 
void clockwise(int Speed) {
  analogWrite(motorIn1, 0);
  analogWrite(motorIn2, Speed);
}

 

2019.2.4 10:00

至此,遥控功能就算完成了。 现在...还..有...点小问题,那就是

  • 单片机连接计算机供电,程序初次启动后约 0.5~1s 内风扇便开始以 rank1=150 运行。
  • 单片机连接 9V 碳性电池(测试环境 1604G 6F22 9V 碳性电池)供电,风扇无法运行,单片机板载 13 LED 持续 快速闪烁 3 次 - 停顿 - 快速闪烁 3 次 - 停顿... 过程。

前者 也说不出来是怎么回事,开始的时候正常,整理了几次电路和代码之后就开始出现这个问题 太丢人了叭,下午调试关于红外的问题的时候才发现这根本就是因为轻触开关按键正负极接反了啊,我居然傻傻的一直错到现在... 后者我开始估计单纯的是电池问题(电量不足,电压不够等等),不过在 Arduino 官方社区看到有类似情况评论区说是 bootloader 出问题还是咋地,感觉像是说单片机底层的问题(英语水平有点堪忧,科技类文献看的也模模糊糊)。

 

2019.2.4 13:00

觉得还是有一个问题,一直以来没有注意。在程序代码完全没问题的情况下,红外信号接收出错我就很无奈了。按下同一个按键多次,单片机接收解析得到的 16 进制红外信号并不是固定的,就像下面这个情况:

Arduino 接收解析红外信号值不固定
Arduino 接收解析红外信号值不固定

我按的一直是遥控上的 1 按键,似乎解析为 0xFF30CF 的情况在正确解析过一个红外信号之后一段时间内只是小概率事件,或者说感觉像猜选择题一样的情景。

 

2019.2.4 14:30

WSY 大神提供了一个链接:《Possible Conflict with IRRemote - Issue#198 Github.com/FastLED/FastLED》 和关键词 定时器冲突 。这个人出现的问题和我的类似。但是尝试过该页代码之后并没有成功,但仍值得参考。核心部分是这个声称可以保证 95% 成功率的模板:

IRrecv irrecv(RECV_PIN);
decode_results results;
 
loop() {
 
    /* do effects here */
 
    while (!irrecv.isIdle());        // if not idle, wait till complete
 
    if (irrecv.decode(&results)) {
 
        /* respond to button */
 
        irrecv.resume();             // Set up IR to receive next value.
    }
    FastLED.show(); 
}

但是我对这一句 while (!irrecv.isIdle()); 的作用还是比较怀疑,作者声称可以在外部程序运行前判断单片机对红外信号的解码处理等是否结束,我在我的程序中加入后效果并不明显。

 

2019.2.4 22:00

给风扇增加了一个 RGB LED 模块,风扇转动时呈蓝色,接收到正确的红外信号时呈红色(方便查看接收的信号是否正确,脱机情况下出错时不必打开电脑 Arduino IDE 的端口监视器查看串口通信数据),轻触按键按下时呈绿色。方便直接对普通用户反馈错误信息。
我根据 WSY 大牛的建议将识别一次红外信号之后的延时函数 delay(); 延长至 3000ms ,有一定效果,但还是不能避免较高的错误率,而且风扇实际体验极差(反应超慢)。

代码:

#include <IRremote.h>
 
/* 原头部定义引脚以及变量代码,这里省略以缩短篇幅 */
 
const int irReceiverPin = 11;
const int RPin = 3;
const int GPin = 5;
const int BPin = 6;
IRrecv irrecv(irReceiverPin);
decode_results results;
  
void irSignalProcess(unsigned long value) {
  switch (value) {
    
    /* 代码与最终代码一致,这里省略以缩短篇幅 */
    
  }
}
 
void setup() {
  
  /* 代码与最终代码一致,这里省略以缩短篇幅 */
  
}
  
void loop() {
   
  /* 原轻触开关按键模块代码,这里省略以缩短篇幅 */
   
  // function for dealing with the signal sent by remotecontroller.
  if (irrecv.decode(&results)) {
    irSignalProcess(results.value);
    Serial.print("Detail Information: irCode:");
    Serial.print(results.value, HEX);
    Serial.print(",bits:");
    Serial.println(results.bits);
    delay(3000);
    analogWrite(RPin,0);
    Serial.println("Delay is end,try to reset the irReceiver.");
    irrecv.resume();
    Serial.println("Reset Success!");
  }
  
  if (reading == HIGH) {
    analogWrite(GPin,255);
  }
  else {
    analogWrite(GPin,0);
  }
  
  if (fanspeed != 0) {
    analogWrite(BPin,255);
  }
  else {
    analogWrite(BPin,0);
  }
   
  /* 原风扇档次 switch case 语句和 loop() 函数后半部分代码,这里省略以缩短篇幅 */
   
}
 
void clockwise(int Speed) {
  analogWrite(motorIn1, 0);
  analogWrite(motorIn2, Speed);
}

 

2019.2.5 2:30

关于 IRremote.h 对红外信号的处理与其他程序结合时,我的理解如下图:

关于红外信号处理程序的浅薄理解
关于红外信号处理程序的浅薄理解

不知道实际上是不是这种情况,又到底该怎么对付红外信号解码异常的问题呢...

 

2019.2.5 15:30

看到几篇教程《解决Arduino的IRremote库与电机库冲突的问题 - 豆瓣》《Arduino红外遥控IRremote扩展库的深入研究----让接受更稳定 - 极客工坊》,个人觉得对问题解决帮助较大,有路过的朋友可以借鉴一下这两篇文章,不过可惜的是两者内容太过时了,毕竟现在都 9102 年了,这两篇文章前者是 2016-02-28 的,后者是 2015-1-13 的,已经差了无数个世纪了好像...不过这促使我去看了看 IRremote.h 的一丢丢内容,有一丢丢开朗的感觉。然后...就没有然后了...

 

2019.2.5 18:30

我又回到 2019.2.4 14:30 的这一句 while (!irrecv.isIdle()); 上来,在读取解码一次之后再次接收红外信号之前加了这一句,然后不断尝试调整 delay(); 函数,虽然可能压根没用,我还是借此安慰自己“会好的,这次应该会好的”、“这个时间应该刚刚好了吧...”。功夫不负有心人,我终于还是没能搞懂这回事,不过试了一下下面最新的代码,效果还算理想。贴在最终代码里了。
这下想把 Arduino 放在一边了。。。歇会,开始好好看微积分。

 

2019.2.7 8:00

突然发现只使用笔记本电源,不利用端口 Serial.print(); 向计算机传送数据后,红外信号识别成功率大幅上升(初步估计在 70% 左右)。难不成是端口传送数据对这红外信号处理解码也有影响???

 

2019.2.17 00:00

跟室友找头像套图翻到了百度贴吧,想一想在家实在闲得无聊不如......安装了百度贴吧后突然想起 Arduino 应该也有一个吧的鸭!于是我来到了 Arduino 吧,嚯!什么人都有,看到还有小白给了张排针的图问这是什么东西...突然有一点想笑哈哈哈哈。咳咳说正事我看到了各路菊苣的代码之后突然想到(其实之前也有想过啦)是不是可以套用类似之前检测按钮开关信号时防止信号持续输入的代码套在红外解码的代码外,这样来限定红外解码启动的间隔呢?
这里主要参考这篇帖子《arduino 红外遥控舵机循环转动》,下面列举一段我认为的关键代码。

//irrecv.resume(); 
if (irrecv.decode(&results)) { 
  if (millis() - last > 250) { 
    on = !on; 
    digitalWrite(13, on ? HIGH : LOW); 
    dump(&results); 
  }
  // irrecv.resume();
  if(results.value== d20) { 
    Serial.println("20 degree");
    //analogWrite(9,50);
    startRun(20); 
  }
  /* ...后面用相同语句对红外信号进行反应 */
}

 

2019.2.18 20:00

接近一个星期没有打开单片机了,前两天把装置都拆了准备到学校再弄,昨晚有了新思路之后立马决定今天来试一试,谁知道今天为哦再次将装置组装在一起,试了试代码,红外遥控竟然神一般的准确。我看了一眼接收红外信号的元件,发现上面的某个电子元件被我放在盒子里压弯了,除此之外我实在是找不出还有什么不同了。

被压歪的 J16409 红外接收元件
被压歪的 J16409 红外接收元件

添加新评论

已有 10 条评论

写这么多代码,累不累。哇塞!!!

MonsterX MonsterX 回复 @TOTO

emmmm....基本思路是一样的,其实也没什么内容哒嘻嘻嘻

这是真正的高手,DSP啊

MonsterX MonsterX 回复 @微信选房

emmm....什么高手,是个想入门的弟弟啦

你怎么那么厉害啊

MonsterX MonsterX 回复 @放空

:aru52: 2333 哪有哪有…才入坑,还不太懂尼!

万能的Arduino :aru15:

MonsterX MonsterX 回复 @Zero

是万能的 Zero ! :aru18:

暖一下 :aru1:

对方向你使用了一个大师球! :aru138: