【问题标题】:Arduino How can i store the last IR code to check if it needs repeating?Arduino 我如何存储最后一个 IR 代码以检查它是否需要重复?
【发布时间】:2019-05-13 13:30:42
【问题描述】:

我正在学习 Arduino,并且连接了直流电机和红外接收器。如果我按下按钮一次,它工作正常,但如果我按住按钮,我不知道如何保持电机旋转,因为 REPEAT 命令是相同的数字。

我想我会存储最后发送的代码并检查重复命令和最后一个代码是否匹配,但它似乎不起作用并且无法弄清楚原因。

#include <IRremote.h>

int IRpin = 11;  // pin for the IR sensor
IRrecv irrecv(IRpin);
decode_results results;
int lastCode;

void setup() {
  // put your setup code here, to run once:
  pinMode(7, OUTPUT);
  pinMode(8, OUTPUT);
  pinMode(9, OUTPUT);
  pinMode(13, OUTPUT);
  Serial.begin(9600);
  irrecv.enableIRIn(); // Enable IR Receiver.
}

void loop() {
  // put your main code here, to run repeatedly:


if

 (irrecv.decode(&results)) {
  Serial.println(results.value);
  irrecv.resume(); 
  Serial.println("Last Code is set to: ");
  Serial.write(lastCode);


  if(results.value== 16748655 || (results.value== 4294967295 && lastCode== 16748655)) // Your ON button value                                       
  {
      digitalWrite(8, HIGH);
      digitalWrite(7, LOW);
      analogWrite(9, 255);
      delay(1000);
      analogWrite(9, 0);
      lastCode= 16748655;

  }


  else if(results.value == 16769055 || (results.value== 4294967295 && lastCode== 16769055)) // Your OFF button value 
  {
      digitalWrite(8, LOW);
      digitalWrite(7, HIGH);
      analogWrite(9, 255);
      delay(1000);
      analogWrite(9, 0);
      lastCode= 16769055;

  }
}


}

【问题讨论】:

  • 您应该避免使用 32 位算术。这是一个老式的 8 位 MCU,而不是 PC。
  • 感谢您的评论,但您的确切意思是什么?
  • Offopic:阅读“神奇数字”
  • 当您让 8 位 AVR 处理 32 位数字时,它必须在机器代码中内联大量软件库,从而使程序非常缓慢。在某些情况下,没有办法绕过它,但在这里你的传感器不可能有 32 位精度,所以你只是让 CPU 无缘无故地咀嚼空气。问题的根源在于编写“irremote.h”的爱好者,从github判断它看起来像一个菜鸟PC程序员。他们还每 50us 触发一次中断。如果 AVR 甚至可以在 50us 内自行处理 ISR 代码,我会感到惊讶……反汇编!
  • @Lundin:但是,results.value 32 位整数,c++ 编译器将优化处理该数字大小。通常,以十六进制格式编写时更易于人类阅读,但这是一个不同的主题。

标签: c++ arduino embedded


【解决方案1】:

在释放按钮之前运行电机的一种更可靠的方法是使用“无代码”超时。也就是说,如果“无代码”状态持续的时间超过自动重复周期,则它已被释放。

在您的代码中不清楚 1 秒模拟脉冲的用途,但是在您的 loop() 函数中放置长时间延迟会使您的系统响应速度大大降低。最好在需要时轮询系统滴答声并“做事”。如果您希望任何人都能理解您的代码并避免维护错误,也应该避免使用幻数。

以下使用系统滴答轮询来实现“无代码”超时。我省略了电机开/关代码,因为不清楚您在 1 秒的延迟中在做什么。

#define NO_CODE        0xFFFFFFFFul
#define MOTOR_ON_CODE  0xFF906Ful
#define MOTOR_OFF_CODE 0xFFE01Ful
#define STOP_TIME_MS   250ul  // stop after button release for 250ms

void loop( )
{
    static unsigned long last_on_time = 0 ; 

    if( irrecv.decode( &results ) )
    {
        irrecv.resume() ;

        unsigned long code = results.value ;

        // If motor off code or no code timeout...
        if( code == MOTOR_OFF_CODE ||
            (code == NO_CODE && millis() - last_on_time > STOP_TIME_MS) )
        {
            // Motor off
            ...
        }
        else if( code == MOTOR_ON_CODE )
        {
            // Continuously update last on time while button is held
            last_on_time = millis() ;

            // Motor on
            ...
        }
    }
}

我已经包含了对电机关闭代码的响应,但这可能不是必需的,因为在任何情况下松开 ON 按钮后电机将关闭 250 毫秒(或您选择的任何时间)。您可能有一个前进/后退按钮,然后释放其中一个以停止:

#define NO_CODE        0xFFFFFFFFul
#define MOTOR_FWD_CODE 0xFF906Ful
#define MOTOR_REV_CODE 0xFFE01Ful
#define STOP_TIME_MS   250ul  // stop after button release for 250ms

void loop( )
{
    static unsigned long last_on_time = 0 ; 

    if( irrecv.decode( &results ) )
    {
        irrecv.resume() ;

        unsigned long code = results.value ;
        switch( code )
        {
            case NO_CODE :
            {
                if( millis() - last_on_time > STOP_TIME_MS )
                {
                    // Motor off
                    ...          
                }
            }
            break ;

            case MOTOR_FWD_CODE :
            {
                // Continuously update last on time while button is held
                last_on_time = millis() ;

                // Motor forward
                ...
            }
            break ;

            case MOTOR_FWD_CODE :
            {
                // Continuously update last on time while button is held
                last_on_time = millis() ;

                // Motor reverse
                ...
            }
            break ;
        }
    }
}

【讨论】:

  • static unsigned long last_on_time = millis() ; 确定这是一个错误?因为它将在.data/default ctor 初始化期间执行很长时间,然后再点击此代码。你也可以将其初始化为STOP_TIME_MS+1; // motor off
  • 另外,我们不应该混合不同类型的十六进制文字。 NO_CODEunsigned long 类型,但 MOTOR_FWD_CODE 等是 long 类型。所以switch 中使用了相互冲突的类型——在这种情况下,什么都不会发生,因为code 是无符号长的,所以你得到了一个转换。但如果是int 等,这里可能会发生细微的错误。始终使用预期类型为十六进制常量添加后缀,在本例中为 ul
  • @Lundin 可能。在实践中,静态是在第一次调用函数时初始化的,但这可能是未定义的。
  • 不,static 变量永远不会在函数被调用时初始化,而是在程序启动期间。
  • @Lundin 所有的优点。我当然无法构建或测试这段代码,它应该被视为一种设计模式,也许不完整甚至不正确。随意解决这些问题。我现在正在打电话,代码编辑并不简单。谢谢。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-09-17
  • 2014-06-24
  • 1970-01-01
  • 2021-06-13
  • 1970-01-01
相关资源
最近更新 更多