Чтение сигнала с прерываниями с помощью Arduino

Я пытаюсь прочитать входной сигнал от источника, который является ШИМ-сигналом. В своем исследовании я нашел несколько полезных статей, найденных здесь: http://www.instructables.com/id/Arduino-Frequency-Detection/?ALLSTEPS и здесь: http://www.camelsoftware.com/2015/12/ 25 / Чтение-ШИМ-сигналов-от-RC-приемника с 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 ответа

Как насчет чего-то вроде этого:

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.

Я думаю, что вы можете использовать свой метод, просто добавив еще один таймер:

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);      
    }  
}
Другие вопросы по тегам