2014-11-03 79 views
0

所以我重写了我的代码。当我按下连接在引脚2上的按钮时,它使引脚13为高电平,并通过收发器将信号发送给接收器(收发器和接收器的类型无关紧要)。我将接收器(引脚13变为高电平)的导线连接到arduino上的引脚7。我还将LED连接到引脚8以指示何时引脚7为高电平。计算信号时间

我的主要焦点是计算按下按钮直到引脚7在Arduino上变为高电平所花费的时间。我使用的是Arduino Leonardo(也是无关紧要的信息)。

这是我的代码:

int buttonState; 
int buttonPin = 2; 
int LbuttonState; // last button state 
int pin13 = 13; 
int pin7state; 
int pin7 = 7; 
int Lpin7state; // last pin 7 state 
int pin8 = 8; 
long startTimeKeeper; 
long endTimeKeeper; 
long elapsedTime; 

void setup() { 
    Serial.begin(9600); 
    pinMode(buttonPin, INPUT); 
    pinMode(pin13, OUTPUT); 
    pinMode(pin7, INPUT); 
    pinMode(pin8, OUTPUT); 
} 

void loop() { 
    buttonState = digitalRead(buttonPin); 

    if(buttonState == HIGH && LbuttonState == LOW) { 
    startTime(); // start the time 
    digitalWrite(pin13, HIGH); 
    LbuttonState = buttonState; 
    } else if(buttonState == HIGH && LbuttonState == LOW) { 
    digitalWrite(pin13, LOW); 
    } else if(buttonState == LOW && LbuttonState == HIGH) { 
    digitalWrite(pin13, LOW); 
    LbuttonState = buttonState; 
    } else//(buttonState == LOW && LbuttonState == LOW) 
    digitalWrite(pin13, LOW); 

    pin7state = digitalRead(pin7); 

    if(pin7state == HIGH && Lpin7state == LOW) { 
    stopTime(); // stop the time 
    digitalWrite(pin8, HIGH); 
    Lpin7state = pin7state; 
    } else if(pin7state == HIGH && Lpin7state == HIGH) { 
    digitalWrite(pin8, HIGH); 
    } else if(pin7state == LOW && Lpin7state == HIGH) { 
    digitalWrite(pin8, LOW); 
    Lpin7state = pin7state; 
    } else//(pin7state == LOW && Lpin7state == LOW) 
    digitalWrite(pin8, LOW); 
} 

void startTime() { 
    startTimeKeeper = millis(); 
} 

void stopTime() { 
    endTimeKeeper = millis();`enter code here` 
    elapsedTime = endTimeKeeper - startTimeKeeper; 
    Serial.print(elapsedTime); 
} 

回答

0

我会建议使用interrupts,特别是因为莱昂纳多支持触发您的两个选择引脚的状态变化中断。

如果我正确理解问题的核心,您希望从引脚2上的按钮上的下降沿(高到低)到引脚7上的上升沿(低到高)之间所经过的时间。如果我误解了这一点,并且你的按钮实际上是高电平有效的,只需将attachInterrupt(interrupt, ISR, mode)的最后一个参数更改为RISING即可。

这些设置完成后,我们指定的中断服务例程(ISR)函数将在指定的状态或状态发生变化时被调用。我们希望在这些ISR中做最少的工作,因为在运行时不会触发其他ISR。记录开始或停止时间将会很好。

但是,中断不能直接使用millis()micros(),因为这些函数本身使用中断。为了解决这个约束,我们将在每个ISR中切换一个简单的标志 - 指示它被触发 - 然后在主循环中轮询该标志值,在那里我们将执行定时器启动/停止动作。为了获得更好的准确性,我在micros()中进行了调整,因为按钮按下和接收到的信号之间的时间应该很小(不管怎样,从来都不是几分钟)。

#define ULONG_MAX 0xFFFFFFFFUL 

unsigned long startTimeKeeper, stopTimeKeeper, elapsedTime; 
volatile boolean buttonFlag = false, signalFlag = false; 

void setup() { 
    Serial.begin(9600); 

    pinMode(2, INPUT); 
    pinMode(7, INPUT); 
    pinMode(13, OUTPUT); 
    pinMode(8, OUTPUT); 

    // Int.2 corresponds to pin 2 
    attachInterrupt(2, buttonPressed, FALLING); 
    // Int.4 corresponds to pin 7 
    attachInterrupt(4, signalReceived, RISING); 
} 

void loop() { 
    // Loop until the buttonPressed ISR sets this flag 
    if (buttonFlag) { 
    // Record the start time 
    startTimeKeeper = micros(); 

    // Do nothing until the signal flag is set by the ISR 
    while (!signalFlag); 

    // Record the end time 
    stopTimeKeeper = micros(); 

    // Normal case - stop time is apparently after start time 
    if (stopTimeKeeper > startTimeKeeper) 
     elapsedTime = stopTimeKeeper - startTimeKeeper; 
    // Overflow case - stop time is apparently before start time 
    else 
     elapsedTime = stopTimeKeeper + (ULONG_MAX - startTimeKeeper); 

    Serial.print(elapsedTime); 

    signalFlag = buttonFlag = false; 
    } 
} 

// Very lightweight ISRs 
void buttonPressed() { 
    buttonFlag = true; 
} 

void signalReceived() { 
    signalFlag = true; 
} 

因为我们马上开始等待signalReceived() ISR激活signalFlag我们注册一个按下按钮后,我们不必担心在这种情况下,去抖动开关太多。

一般情况下,您需要使用物理电路或软件计数器来消除您的开关。查看this tutorial以开始使用软件,或者查看here了解有关建筑物去抖电路的信息。