Как измерить временной интервал между двумя входами на pin2 в Arduino? - PullRequest
1 голос
/ 12 апреля 2020

Я хочу измерить временной интервал между двумя входными импульсами на выводе 2 Arduino UNO, используя метод прерывания по таймеру, и я написал этот код, но он не работает должным образом.

Этот код показывает только один момент времени поэтому я не могу измерить временной интервал. Я новичок в Arduino и пытаюсь сделать вентилятор. Любое предложение будет оценено. Спасибо!

//Three timer interrupts
//timer setup for timer0,timer1 and timer2
//this code will enable all three arduino uno timer interrupts
//timer0 will interrupts at 2 KHz
//timer1 will interrupts at 1 Hz
//timer2 will interrupts at 8 KHz

//storage variables
boolean toggle0=0;
boolean toggle1=0;
boolean toggle2=0;

long count0=0;
long count1=0;
long count2=0;
float t=0;
float iT =0;
float fT =0;
float temp=0;
int switchPin = 2;
int switchState = 0;

void setup() {

    cli(); //stop interrupts

    //set timer0 interrupts at 2 KHz
    TCCR0A = 0;//set entire TCCR0A register to 0
    TCCR0B = 0;
    TCNT0 = 0; //initialize counter value to 0

    //set compare match register for 2KHz increments
    OCR0A = 124;//=(16x10^6)/(2000x64)-1(must be <256)
    //turn on CTC mode
    TCCR0A |=(1 << WGM01);
    //set CS01 and CS00  bits for 64 prescaler
    TCCR0B |= (1 << CS01) | (1 << CS00);
    //enable timer compare interrupt
    TIMSK0 |= (1 << OCIE0A);

    //set timer0 interrupts at 1 Hz
    TCCR1A = 0;//set entire TCCR1A register to 0
    TCCR1B = 0;
    TCNT1 = 0; //initialize counter value to 0

    //set compare match register for 1 Hz increments
    OCR1A = 15624;//=(16x10^6)/(1x1024)-1(must be <65536)
    //turn on CTC mode
    TCCR1B |=(1 << WGM12);
    //set CS12 and CS10  bits for 1024 prescaler
    TCCR1B |= (1 << CS12) | (1 << CS10);
    //enable timer compare interrupt
    TIMSK1 |= (1 << OCIE1A);

    //set timer0 interrupts at 8 KHz
    TCCR2A = 0;//set entire TCCR2A register to 0
    TCCR2B = 0;
    TCNT2 = 0; //initialize counter value to 0

    //set compare match register for 2KHz increments
    OCR2A = 249;//=(16x10^6)/(8000x8)-1(must be <256)
    //turn on CTC mode
    TCCR2A |=(1 << WGM21);
    //set CS21  bits for 8 prescaler
    TCCR2B |= (1 << CS21);
    //enable timer compare interrupt
    TIMSK2 |= (1 << OCIE2A);

    sei();//allow interrupts

    pinMode(switchPin,INPUT);
    Serial.begin(9600);
}

ISR(TIMER0_COMPA_vect){

    //timer0 interrupts 2KHz toggles pin 8
    //generate pulse wave of frequency 2KHz/2 = 1KHz
    if(toggle0){
        digitalWrite(8,HIGH);
        toggle0 = 0;
        count0++;
        t = count0/1000;
    }
    else {
        digitalWrite(8,LOW);
        toggle0 = 1;
    }
}

ISR(TIMER1_COMPA_vect){

    //timer1 interrupts 1Hz toggles pin 8
    //generate pulse wave of frequency 1Hz/2 = 0.5Hz
    if(toggle1){
        digitalWrite(13,HIGH);
        toggle1 = 0;
        count1++;

    }
    else {
        digitalWrite(13,LOW);
        toggle1 = 1;
    }
}

ISR(TIMER2_COMPA_vect){

    //timer2 interrupts 8KHz toggles pin 8
    //generate pulse wave of frequency 8KHz/2 = 4KHz
    if(toggle2){
        digitalWrite(9,HIGH);
        toggle2 = 0;
        count2++;

    }
    else {
        digitalWrite(9,LOW);
        toggle2 = 1;
    }
}

void loop() {

    switchState = digitalRead(switchPin);
    if ((switchState == 1) && (temp == 0)) {
        temp = 1;
    }
    if ((switchState == 1) && (temp == 1)) {
        temp = 0;
    }

    if(switchState){
        if(temp == 0) {
            iT = t;
        }
        if(temp == 1) {
            fT = t;
        }
    }

    //Serial.println(t);
    //Serial.print("Count0 :");
    //Serial.println(count0);

    //Serial.print("count1 :");
    //Serial.println(count1);

    //Serial.print("count2 :");
    //Serial.println(count2);

    // Serial.print("Time : ");
    //Serial.println(t);
    //Serial.println(switchState);
    Serial.print("First Ping Time :: ");
    Serial.println(iT);
    Serial.print("Second Ping Time :: ");
    Serial.println(fT);
    //Serial.print("Temp=");
    //Serial.println(temp);
}

и вывод, показывающий:

Second Ping Time :: 0.00
First Ping Time :: 4.00
Second Ping Time :: 0.00
First Ping Time :: 4.00
Second Ping Time :: 0.00
First Ping Time :: 4.00
Second Ping Time :: 0.00
First Ping Time :: 4.00
Second Ping Time :: 0.00
First Ping Time :: 4.00
Second Ping Time :: 0.00
First Ping Time :: 4.00
Second Ping Time :: 0.00
First Ping Time :: 4.00
Second Ping Time :: 0.00
First Ping Time :: 4.00
Second Ping Time :: 0.00
First Ping Time :: 4.00
Second Ping Time :: 0.00
First Ping Time :: 4.00
Second Ping Time :: 0.00
First Ping Time :: 4.00

Ответы [ 2 ]

1 голос
/ 14 апреля 2020

Я бы подошел к этой проблеме проще. Всегда старайтесь разделить проблему на более мелкие (не слишком много!). В этом случае нам нужно:

  • Начать принимать время, когда изменяется состояние.
  • Время занять.
  • Прекратить брать время, когда мы получаем другой вход.

Давайте начнем:

Начните с момента, когда состояние изменится.

Если мы считаем, что состояние вывода по умолчанию - LOW, код должен учитывать, что ввод HIGH, так что это будет первый оператор в нашем разделе loop(). Функция для считывания статуса вывода - digitalRead(). В качестве значения вы указываете пин-код, который нам интересен, и мы получим статус HIGH или LOW.

if (digitalRead(pin) == HIGH){
}

Время.

Теперь мы знаю, когда начинать время, поэтому пришло время подумать о том, как мы собираемся его принять. Мы можем написать это внутри оператора if или создать новую функцию, это зависит от того, как вы собираетесь использовать свой код. Давайте реализуем это непосредственно в операторе if. Мы можем просто добавить 1 к переменной в al oop, что-то вроде:

elapsedTime = 0;
for (int i = 0; i <= 255; i++){
    elapsedTime = elapsedTime + 1;
}

Но мы хотим увеличивать единицу через определенное время, секунду. Мы можем сказать доске эй! подождите одну секунду после добавления одного . Достижение этой цели достигается путем ожидания одной секунды с функцией delay(). Нам нужно указать, сколько, в данном случае, 1000, потому что одна секунда составляет 1000 миллисекунд. Подробнее о функции, здесь . Теперь наш код выглядит следующим образом:

elapsedTime = 0;
for (int i = 0; i <= 255; i++){
    elapsedTime = elapsedTime + 1;
    delay(1000);
}

Более распространенный способ добавить следующий код: variable++. Еще одно незначительное редактирование будет ждать одну секунду, прежде чем добавить одну, потому что, когда вы начинаете время, которое вы хотите сохранить 0, нет 1. Давайте перепишем эти строки:

elapsedTime = 0;
for (int i = 0; i <= 255; i++){
    delay(1000);
    elapsedTime = elapsedTime++;
}

Хватит тратить время, когда мы получаем другое input.

Теперь, вместо того, чтобы ждать это до 255 секунд, мы хотим выполнить эту операцию, пока не вернемся к нашему активированному состоянию нашего вывода (HIGH). В этом случае мы используем while, что означает что-то вроде Эй, доска! выполняйте эту операцию до тех пор, пока что-то

while (digitalRead(pin) == LOW){
}

Теперь то, что мы пишем внутри этой функции, будет выполняться до тех пор, пока мы не получим ложное утверждение. Используя то, что мы написали ранее:

elapsedTime = 0;
while (digitalRead(pin) == LOW){
    delay(1000);
    elapsedTime = elapsedTime++;
}

Наконец, мы хотим начать подсчет, когда мы получим первый HIGH ввод, поэтому мы заключаем его в первую строку кода:

elapsedTime = 0;
if (digitalRead(pin) == HIGH){
    while (digitalRead(pin) == LOW){
        delay(1000);
        elapsedTime = elapsedTime++;
    }
}

Все готово! Чтобы получить результат, вы можете распечатать результат, или делать все, что вы хотите. Вместо времени в секундах вы можете измерить любую единицу, просто измените значение внутри delay() на любое другое значение. Например, если мы хотим измерить миллисекунды, это будет delay(1).

1 голос
/ 12 апреля 2020

Прежде всего не стоит связываться с timer0. Arduino использует TIMER0 для синхронизации. Вы не должны изменять это (так как вы узнали, что это останавливает работу millis ()). Вы можете делать все, что вы хотите с TIMER1 и TIMER2. (хотя некоторые библиотеки используют их). Почему бы не использовать attachInterrupt ()?
Прочтите здесь, чтобы узнать, как , и посмотрите здесь, например, код Извините, что не копались в вашем длинном коде.

...