我试图计算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
条件)?以下是微波传感器的逻辑分析仪输出:
编辑:如果我在delay(1);
之前添加if
,则计数器不再为0。
答案 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.