【问题标题】:Reading signal with interrupts using arduino使用arduino读取带有中断的信号
【发布时间】:2016-09-08 18:31:14
【问题描述】:

我正在尝试从 PWM 信号源读取输入信号。在我的研究中,我在这里找到了一些有用的文章:http://www.instructables.com/id/Arduino-Frequency-Detection/?ALLSTEPS 和这里:http://www.camelsoftware.com/2015/12/25/reading-pwm-signals-from-an-rc-receiver-with-arduino/。第一篇文章有​​点超出我的经验水平,如果我使用除 uno 以外的任何东西,它也无济于事,尽管它似乎表现得非常好。第二个显示了一种我更容易理解的方法。

我已经成功地使用了以下代码:

#define input_pin 2

volatile unsigned long timer_start;
volatile int pulse_time;

volatile int last_interrupt_time;  
void calcSignal() 
{
    last_interrupt_time = micros(); 

    if(digitalRead(input_pin) == HIGH) 
    { 
       timer_start = micros();
    }  
    else {   
       if(timer_start != 0)
       { 
           //record the pulse time
           pulse_time = ((volatile int)micros() - timer_start);
           //restart the timer
           timer_start = 0;
       }
    } 
} 


void setup() 
{
    timer_start = 0; 
    attachInterrupt(0, calcSignal, CHANGE);
    Serial.begin(115200);
} 

void loop()
{
    Serial.println(pulse_time);
    delay(20);
} 

此设置对我的应用程序的问题是中断仅由状态更改触发,而实际上我需要知道它的高电平持续时间和低电平持续时间。在此处可以看到具有各种占空比的理想信号图片 (https://www.arduino.cc/en/Tutorial/SecretsOfArduinoPWM)。我尝试将中断模式从 CHANGE 更改为 LOW 和 HIGH,但没有得到任何可靠的结果,因为它只在串行监视器上输出零。是否有我遗漏的东西或可以使用的替代库/方法?我对编程有点陌生,所以有点了解,但绝不是程序员。

【问题讨论】:

  • 只是想知道 - 这种测量 PWM 的方法如何处理 0% 和 100% 的 PWM 比率?谢谢,
  • @MichaelVincent 我没有尝试过 100% pwm 信号,但我尝试过 0% 信号(拔下输入),它会在串行监视器上打印一个零流。
  • 谢谢。我认为您的代码可能存在逻辑问题。它可能永远不会发生,或者很少发生。假设您有 77% 占空比的 PWM 输入。输入变低,您获取新的开始时间,然后 PWM 占空比变为 0%。 pulse_time 会更新为显示 0,还是会继续显示 77% ?我认为这个问题(如果存在)也存在于宏的代码中。亲切的问候,
  • @MichaelVincent 我怀疑有类似的想法,但是我不熟悉中断方法,并在解释读取 pwm 信号的各种方法的站点上找到了此代码。话虽如此,它很可能有错误。我要搞砸它,看看我得到什么类型的结果。
  • 我希望我有一个解决方案 - 我确定有一个 - 但我没有。我正在考虑从传感器读取 PWM 输入,但占空比范围不会扩展到 0 或最大 100。所以这里的代码对我有用 - 根据您的应用程序可能很适合您。祝您的项目一切顺利,

标签: arduino interrupt atmega pwm


【解决方案1】:

这样的事情怎么样:

unsigned long     timeout = 100000L; // reasonable timeout around 100ms?
unsigned long     high_us = pulseIn(pinNo, HIGH, timeout);
unsigned long      low_us = pulseIn(pinNo, LOW,  timeout);
unsigned long thousandths = (high_us*1000) / (high_us+low_us);

但是它无法测量一个周期HI/LO。它将在其中两个上进行测量:>HI< lo hi >LO<

如果这不是您想要的,您可以深入研究 AVR DataSheet 并尝试让 Timer Input Capture 中断工作。

【讨论】:

    【解决方案2】:

    我认为您可以使用您的方法,只需添加另一个计时器:

    void calcSignal()  {
        if(digitalRead(input_pin) == HIGH) 
        { // transition from LOW to HIGH
           timerH_start = micros();
           //record the pulse time 
           pulse_time_L = ((volatile int)micros() - timerL_start);
        }  
        else { // transition from HIGH to LOW
           timerL_start = micros();   
           //record the pulse time 
           pulse_time_H = ((volatile int)micros() - timerH_start);      
        }  
    }
    

    【讨论】:

    • 这种方法似乎在我想做的事情的正确轨道上。我今天要搞砸它,看看我得到了什么。谢谢。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2022-11-01
    • 2022-01-07
    • 2023-02-02
    • 2020-10-19
    • 2014-09-30
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多