用于数字读取和计数脉冲的Arduino uno中的CPU周期

时间:2017-02-06 07:25:49

标签: arduino arduino-uno pulse cpu-cycles

我试图计算200ms时间量子中HB100 microwave sensor个脉冲的数量。

以下是代码:

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

我需要知道数字读取周期。 我将传感器的最后状态与当前状态进行比较,如果进行了更改(从低到高),计数器会递增。但是,我的计数器总是0

  • 代码是否正确(if条件)?
  • 我需要一些延迟吗?
  • 是否可以计算这些脉冲?

以下是微波传感器逻辑分析仪输出:

enter image description here

编辑:如果我在delay(1);之前添加if,则计数器不再为0。

3 个答案:

答案 0 :(得分:2)

由于这些脉冲似乎甚至短于微秒,你只能使用需要大约80个机器周期的digitalRead函数(大约5us @16MHz)。

更不用说在每个循环迭代中打印如此多的数据!!!!

因此,您的频率超过1MHz,您的代码可能会计入10kHz(充其量,可能更少)

无论如何,您应该在Timer/Counter 1输入上使用带有时钟源的HW 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.

每200ms只读TCNT1并最终重置为0或只记住最后一个值并产生差异(不要忘记它只是16b数字)。

答案 1 :(得分: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

答案 2 :(得分: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.

作为第二种解决方案,您可以设置和取消设置引脚并使用逻辑分析仪计算时间。

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.