计算信号时间

标签 c arduino microcontroller arduino-uno arduino-yun

所以我重写了我的代码。当我按下连接在引脚 2 上的按钮时,引脚 13 会变为高电平,并通过收发器向接收器发送信号(收发器和接收器的类型无关)。我将一根电线从接收器(其中引脚 13 使其变为高电平)连接到 arduino 上的引脚 7。我还将 LED 连接到引脚 8,以指示引脚 7 何时处于高电平。

我的主要关注点是计算从按下按钮到 Arduino 上的引脚 7 变为高电平所需的时间。我正在使用 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);
}

最佳答案

我建议使用 interrupts ,特别是因为 Leonardo 支持在您选择的两个引脚的状态更改时触发中断。

如果我正确理解问题的核心,您需要从引脚 2 上的按钮按下的下降沿(高到低)到引脚 7 上的上升沿(低到高)之间耗时。如果我误解了并且您的按钮实际上是高电平有效,只需将 attachInterrupt(interrupt, ISR, mode) 的最终参数更改为 RISING

这些设置完成后,只要指定的状态或状态发生变化,就会调用我们指定的中断服务例程(ISR)函数。我们希望在这些 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有关构建去抖电路的信息。

关于计算信号时间,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26712701/

相关文章:

c - 它是头文件还是库?在生成文件中

arduino - 用arduino读入传感器数据(GPS原始数据)并将其存储在SD卡上

c - 从 LDR 中获取值(value)

来自不同 C 字符串数组的堆栈上的 C 字符串大小

c - C 中的字数统计程序计数不正确

无法解决此c程序中的内存管理(valgrind)

计算2个内存地址之间的距离

c++ - 数组一直只返回最后一个元素。 [C/阿杜伊诺]

algorithm - Arduino凸包算法

c - 使用键盘作为标准输入