2017-02-06 5 views
3

Я пытаюсь подсчитать количество HB100 microwave sensor импульсов в 200ms квантах времени.Циклы процессора в Arduino uno для цифровых импульсов чтения и подсчета

Вот код:

#include <SoftwareSerial.h> 
#include <elapsedMillis.h> 
elapsedMillis ElapsedTime; 

#define Sensor A0 
#define TimeQuanta 200 

int Counter = 0; 
boolean LastState; 

void setup() 
{ 
    Serial.begin(250000); 
    pinMode(Sensor, INPUT); 
} 

void loop() 
{ 
    Counter = 0; 
    ElapsedTime = 0; 
    while (ElapsedTime < TimeQuanta){ 
    LastState = digitalRead(Sensor); 
    if (LastState == LOW && digitalRead(Sensor) == HIGH){ 
     Counter += 1; //Compare Last state with current state 
    } 
    } 
    Serial.print(digitalRead(Sensor)); 
    Serial.print("\t"); 
    Serial.println(Counter); 
} 

мне нужно знать цифровые циклы чтения. Я сравниваю последнее состояние датчика с текущим состоянием, и если выполняется изменение (LOW TO HIGH), счетчик увеличивается. Тем не менее, мой счетчик всегда 0!

  • - правильный код (состояние if)?
  • Мне нужны задержки?
  • Можно ли считать эти импульсы?

Вот Logic Analyzer выход микроволновый датчик:

enter image description here


Edit: если я добавляю delay(1); перед тем if то счетчик не 0 больше.

ответ

2

Вы можете использовать timer1 для расчета прошедшего времени.

// Set Timer1 without prescaler at CPU frequency 
TCCR1A = 0; // TCCRx - Timer/Counter Control Register. The pre-scaler can be configured here. 
TCCR1B = 1; 

noInterrupts(); // Disable interrupts. 

uint16_t StartTime = TCNT1; // TCNTx - Timer/Counter Register. The actual timer value is stored here. 
digitalRead(pin); // your code. 
uint16_t EndTime = TCNT1 
uint16_t ElapsedTime = EndTime - StartTime; 

interrupts(); //Enable interrupts. 

В качестве второго решения вы можете установить и отключить вывод и вычислить время с помощью Logic Analyzer.

DDRD = DDRD | B10000000; // Set digital pin 7 as output. 
PORTD = PORTD | B10000000; // Set digital pin 7. 
digitalRead(pin); // your code. 
PORTD = PORTD & B01111111; // Unset digital pin 7. 
2

Поскольку эти импульсы кажутся даже меньше, чем микросекунды, вы просто не можете использовать функцию digitalRead, которая занимает около 80 машинных циклов (около 5us @16MHz).

Не говоря уже о печати большого количества данных в каждой отдельной итерации цикла !!!!

Так у вас есть частоты более 1MHz и ваш код может быть в состоянии рассчитывать около 10kHz (в лучшем случае, может быть меньше)

Во всяком случае, вы должны использовать HW Timer/Counter 1 с источником синхронизации на T1 входе. Это одна возможность подсчета импульсов в половине основной тактовой частоты (50% ширины импульса)

И использование Timer/Counter 1 довольно прост:

TCCR1A = 0; // default mode, no output compare modes 
TCCR1B = _BV(CS10) | _BV(CS11) | _BV(CS12); // clock select mode 7 - External clock source on T1 pin. Clock on rising edge. 

И каждые 200мс просто читать TCNT1 и в конечном итоге сбрасывается в 0 или просто помните последнее значение и делайте разницу (не забывайте, что это всего лишь номер 16b).

+0

Спасибо за ваш ответ, где я могу найти документ для циклов процессора для любой операции? Отпечатки теперь находятся вне цикла while. – Mehran

+0

Вряд ли я использовал свой собственный «тест». Но можно переключать некоторый выход и измерять частоту. Может быть, есть некоторые статьи по этой теме. – KIIV

2

KIIV очень хорошо объяснил, почему ваш код не работает, здесь я хотел бы предложить альтернативный подход, который достигает той же цели.


Код:

const byte interruptPin = 2; 
volatile unsigned long counter = 0;    // overflow after 2^32-1 pulses 

void setup() { 
    pinMode(interruptPin, INPUT_PULLUP); 
    attachInterrupt(digitalPinToInterrupt(interruptPin), count, RISING); 
    Serial.begin(19200); 
} 

void loop() { 
    Serial.print("No. pulses: "); 
    Serial.println(counter); 
    delay(1000); 
} 

void count() { 
    counter++;          // never use print() in an ISR! 
} 

Пожалуйста, обратите внимание, что я изменил входной контакт, потому что есть некоторые restrictions на булавки, которые могут быть использованы с этой техникой, которые зависят от платы вы используете:

Board        Digital Pins Usable For Interrupts 
Uno, Nano, Mini, other    2, 3 
Mega, Mega2560, MegaADK    2, 3, 18, 19, 20, 21 
Micro, Leonardo, other 32u4-based 0, 1, 2, 3, 7 
Zero         all digital pins, except 4 
MKR1000 Rev.1      0, 1, 4, 5, 6, 7, 8, 9, A1, A2 
Due, 101        all digital pins 
+0

Спасибо, я прочитаю упомянутый документ и протестирую код. Мне нужно непрерывно подсчитывать импульсы в 200 мс, так что задержка Ithink (1000) не подходит. – Mehran

+1

Задержка находится над функцией ** print **, импульсы подсчитываются ** постоянно ** с использованием ** процедуры обслуживания прерывания ** 'count()'. Вы можете уменьшить * задержку *, но только до определенной степени. Современная реализация * Arduino * использует * прерывания * для работы с 'print()', а это означает, что если вы злоупотребляете этой инструкцией, вы можете пропустить * некоторые импульсы * или иметь другое странное поведение. Учитывая высокую частоту ваших импульсов, вы, конечно же, не хотите использовать 'print()' после каждого импульса. Возможно, * каждая 100/1000 импульсов * может быть лучшей идеей. –

+0

Ваш код работает. Я раньше не использовал ISR, я буду читать больше, спасибо за ваше предложение. – Mehran