0
votes

So i have rewritten my code. when I press the button connected on pin 2 it makes pin 13 HIGH and it sends a signal via a transceiver to a receiver (type of transceiver and receiver is irrelevant). I connected a wire from the receiver(where pin 13 makes it HIGH) to pin 7 on the arduino. Also I connected a LED to pin 8 to indicate when pin 7 is HIGH.

My main focus is to calculate the time it took from pressing the button until pin 7 is made HIGH on the Arduino. I am using a Arduino Leonardo( also irrelevant information).

This is my code :

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

1 Answers

0
votes

I would suggest using interrupts, especially since the Leonardo supports interrupts triggered on state changes of both of your chosen pins.

If I understand the core of the problem correctly, you want the time elapsed between a falling edge (HIGH to LOW) from your button press on pin 2 to a rising edge (LOW to HIGH) on pin 7. If I misinterpreted that and your button is actually active-high, just change the final parameter of attachInterrupt(interrupt, ISR, mode) to RISING.

After these are setup, our specified interrupt service routine (ISR) functions will be called whenever the specified state or state change occurs. We want to do minimal work in these ISRs since no other ISR can be triggered while one is running. Recording a start or stop time would be fine.

However, interrupts cannot use millis() or micros() directly because those functions themselves use interrupts. To work around that constraint, we'll toggle a simple flag of our own in each ISR--to indicate that it was triggered--then poll for that flag value in the main loop, where we'll do our timer start/stop actions. I subbed-in micros() for better accuracy since the time between a button press and a signal received should be small (never on the order of minutes, anyway).

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

Since we immediately begin waiting for the signalReceived() ISR to activate signalFlag after we register a button press, we don't have to worry too much about debouncing the switch in this case.

In general, you'll want to debounce your switches, either with physical circuitry or software counters. Check out this tutorial to get started with software, or look here for information on building debounce circuits.