当前位置: 首页 > 知识库问答 >
问题:

Arduino:我如何解决在类定义中使用ISR的PWM读数中的可靠性问题?

仇建茗
2023-03-14

我正在尝试使用Arduino MEGA 2560和硬件中断读取PWM信号的占空比。我很清楚在定义为类成员函数的ISR中使用attachInterrupt函数会出现的问题,但我找到了解决问题的方法。我的代码部分正常工作,但有两个问题:

  1. 中断工作不可靠。在用固件闪烁Arduino之后,ISR有时会表现为根本没有被触发,将占空比保持在0(当它初始化时)。
  2. 当测量占空比时,占空比(先验已知为常数)会保持随机快速变化,即使在类定义之外用作正则函数的相同ISR也能正确可靠地工作。

我的问题是:在我的“面向对象”实现和常规的“功能性”实现之间,有什么隐藏的差异是我看不到的?我在下面发布了两个实现的代码。

代码一:“功能性”实现

    #define PWM_CHANNEL 2
volatile int pwmDutyCycle_throttle = 0;

void setup() {
  Serial.begin(115200); // Serial to PC
  attachInterrupt(digitalPinToInterrupt(PWM_CHANNEL), decodePwm_1, CHANGE);
}

void loop() {
  int localValue;
  noInterrupts();
  localValue = pwmDutyCycle_throttle;
  interrupts();
  Serial.println(pwmDutyCycle_throttle);
}

void decodePwm_1() {
  static unsigned long riseTime = micros(); // initialize riseTime
  if (digitalRead(PWM_CHANNEL_1) == 1) { // the signal has risen
    riseTime = micros(); // save the rise time
  }
  else { // the signal has fallen
    pwmDutyCycle_throttle = micros() - riseTime; // compute the duration of the high pulse
  }
}

代码2:“面向对象”实现:

#define PWM_CHANNEL 2
typedef  byte pin_t;
typedef uint16_t pulse_t;

class pwm_reader_attachable_t {
    uint8_t pin;          /**< physical pin on the board */
    volatile uint16_t pulse;      /**< duration of the high edge (the pwm reading) */
    uint16_t pulse_real; /**< a stabilized version of the reading (for fast varying signals) */
    uint16_t edge_time;  /**< timing of the last high edge */
    uint8_t counter;  /**< counter (actually used for the encoder) */
    uint8_t read;         /**< Last reading of the pin, for triggering pulse width evaluation */
  public:
    void setup(pin_t pin, void (*ISR_callback)(void), int value);
    void  handleInterrupt(void);
    inline pulse_t get_pulse() {
      pulse_t x;
      noInterrupts();
      x = pulse;
      interrupts();
      return x;
    };

    pwm_reader_attachable_t(void) {
      counter = 0;
      pulse = 0;
      pulse_real = 0;
      edge_time = 0;
      read = 0;
    }

  private:
    void(*ISR_callback)();
};

void pwm_reader_attachable_t::setup(pin_t pin, void (*ISR_callback)(void), int value)
{

  //pinMode(pin, INPUT_PULLUP);
  attachInterrupt(digitalPinToInterrupt(pin), ISR_callback, value);
  interrupts();
}

inline void pwm_reader_attachable_t::handleInterrupt(void)
{
  static unsigned long riseTime = micros(); // initialize riseTime
  if (digitalRead(pin) == 1) { // the signal has risen
    riseTime = micros(); // save the rise time
  }
  else { // the signal has fallen
    pulse = micros() - riseTime; // compute the duration of the high pulse
  }
}

pwm_reader_attachable_t* motor;
pulse_t DC = 0;

void setup()
{
  Serial.begin(115200);
  motor = new pwm_reader_attachable_t();
  motor->setup(PWM_CHANNEL, [] {motor->handleInterrupt();}, CHANGE);
  //motor->setup(PWM_CHANNEL, motor->handleInterrupt, CHANGE);
}

void loop()
{
  DC = motor->get_pulse();
  Serial.println(DC);
}

谢谢!

共有1个答案

阴阳
2023-03-14

在函数实现中,调用AttachInterrupt()时,将函数DecodePWM_1()的地址作为函数指针传递。这是有意义的,并暗示在需要时将调用该函数。

在面向对象的版本中,您调用attachInterrupt(),传递一个未初始化的变量,即私有变量ISR_Callback。您可能希望该变量指向处理程序函数handleinterrupt()。初始化它的最佳位置是pwm_reader_attachable_t的构造函数

 类似资料:
  • 你好想问一下,刚刚接触react,之前写的js在html上可以使用,但是换到这里显示document is not defined,如果在document.getElementById不能用的情况下还有什么办法能够通过id获取到元素?或者应该怎么修改才能正常获取呢?写的屎山如下,请大佬指教qaq 1

  • 我有两个文件,一个是'a.js'在压缩文件夹中,另一个是b.js在压缩文件夹中的一个文件夹b中,我正在使用Express的路由。我是一个初学者,不知道如何解决这个错误,它意味着什么。我想在a.js中使用b文件。A.JS 这是B.JS 这是错误 This.Stack.Push(层);^ TypeError:无法读取function.route(C:\users\palwasha\downloads\

  • 我面临这个问题,当我假设通过n并找到从范围[0,2次方n-1]中选择x的方法的数目时,使得x^(x+1)=(x+2)^(x+3)其中^表示异或运算符。由于有效x的数目可能很大,因此输出它的模为10^9+7。

  • 在基类中,我有一个函数,它接受一个字符串文件名,构造一个功能集,并将其工作延迟到一个纯虚拟函数。 在子类中,我实现了这个虚拟函数。 在中,我有一个子类的实例,并使用一个文件名调用。我以为这将调用基类的非虚拟函数,该函数接受字符串参数,但这并不能编译。错误是: 掠夺。cpp:在函数“int main()”中: 掠夺。cpp:33:48:错误:调用“SubClass::GetDetections(co

  • 在我的Android Studio项目中,我在gradle中定义了代理设置。与Git repo同步的属性文件。只要在那里定义了代理密码,我就需要将其移动到本地。属性文件。我想实现这样的smth: 在gradle.properties: 在当地。特性: 我该怎么做?

  • 我面临这个问题,当我假设通过n并找到从范围[0,2次方n-1]中选择x的方法的数目时,使得x^(x+1)=(x+2)^(x+3)其中^表示异或运算符。由于有效x的数目可能很大,因此输出它的模为10^9+7。