0

だから私は自分のコードを書き直しました。ピン2に接続されているボタンを押すと、ピン13がHIGHになり、トランシーバーを介してレシーバーに信号が送信されます(トランシーバーとレシーバーのタイプは関係ありません)。レシーバー(ピン13がHIGHになる場所)からarduinoのピン7にワイヤーを接続しました。また、ピン7がHIGHであることを示すために、ピン8にLEDを接続しました。

私の主な焦点は、ボタンを押してから Arduino でピン 7 が HIGH になるまでにかかった時間を計算することです。私は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);
}
4

1 に答える 1

0

特にレオナルドは、選択した両方のピンの状態変化でトリガーされる割り込みをサポートしているため、interruptを使用することをお勧めします。

問題の核心を正しく理解していれば、ピン 2 のボタン押下からピン 7 の立ち上がりエッジ (LOW から HIGH) までの立ち下がりエッジ (HIGH から LOW) までの経過時間が必要になります。ボタンは実際にはアクティブ ハイです。最後のパラメータを に変更するだけattachInterrupt(interrupt, ISR, mode)ですRISING

これらがセットアップされると、指定された状態または状態変化が発生するたびに、指定された割り込みサービス ルーチン (ISR) 関数が呼び出されます。1 つの ISR の実行中に他の ISR をトリガーすることはできないため、これらの ISR で最小限の作業を行いたいと考えています。開始時間または停止時間を記録することは問題ありません。

ただし、これらの関数自体が割り込みを使用するため、割り込みはmillis()ormicros()を直接使用できません。この制約を回避するには、各 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この場合、スイッチのデバウンスについてあまり心配する必要はありません。

一般に、物理回路またはソフトウェア カウンターのいずれかを使用して、スイッチのデバウンスを行う必要があります。ソフトウェアの使用を開始するには、このチュートリアルを参照するか、デバウンス回路の構築に関する情報については、こちらを参照してください。

于 2014-11-25T08:48:36.693 に答える