使用arduino读取中断信号

时间:2016-09-08 18:31:14

标签: arduino interrupt atmega pwm

我试图从作为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,但没有得到任何可信的结果,因为它只在串行监视器上输出零。是否有我缺少的东西或可以使用的替代库/方法?我对编程有些新意,所以我有一些了解,但绝不是程序员。

2 个答案:

答案 0 :(得分:0)

这样的事情:

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中断工作。

答案 1 :(得分:0)

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

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);      
    }  
}