
// shutter tester for Arduino Nano.
// https://www.photrio.com/forum/threads/build-a-shutter-tester-for-focal-plane-shutters-cheap-easy-it-works.197756/
// If you use this code & build a tester, please say 'Hi' & 'Thank You' and post photos of your creation in the thread above.
// For help & assistance with building, post a link in the thread above.

// String Ver =  "version 3.0.1";
// String Date = "4 April 2023";

// *********************************************************************************************************
// newer laser sensors may have a reversed output. They can be changed by swapping the two active lines below
const bool seen    = true;     // un-comment this line (older sensors)
const bool blocked = false;    // AND this line        (older sensors)

// const bool seen    = false;  // OR this line       (newer sensors)
// const bool blocked = true;   // AND this line      (newer sensors)
//
// Note:- comments in code always refer to older sensors i.e 'if the voltage on pin2 is high'.
//        On newer sensors, electrically, they would be low, however this does not matter (unless you
//        are poking around with a voltmeter). Just comment/uncomment the two lines of code above.
//        There is a test program (sketch) in the photro thread (link above) that is a quick way to see if
//        your sensors are the newer type.
// *********************************************************************************************************


#include <Wire.h>               // built in library
#include <LiquidCrystal_I2C.h>  // by Frank de Brabander
#include <LibPrintf.h>          // https://github.com/embeddedartistry/arduino-printf
#include <RunningAverage.h>     // https://github.com/RobTillaart/RunningAverage

LiquidCrystal_I2C lcd(0x27, 20, 4);  // set the LCD address. Normally 0x27 for a 20 char 4 line display


// define variables. Vars ending 1 are first laser or first curtain. Vars ending 2 are second laser or second curtain.

RunningAverage SSMILLISAV1 (10);               // define average counters
RunningAverage SSMILLISAV2 (10);               // define average counters
RunningAverage SHCURTAINSPEEDMILLISAV1 (10);   // define average counters
RunningAverage SHCURTAINSPEEDMILLISAV2 (10);   // define average counters


unsigned long Start1; // Arduino microsecond clock time when laser1 seen (uncovered by shutter curtain)
unsigned long Stop1;  // Arduino microsecond clock time when laser1 blocked (by shutter curtain)
unsigned long Start2; // Arduino microsecond clock time when laser2 seen (uncovered by shutter curtain)
unsigned long Stop2;  // Arduino microsecond clock time when laser2 blocked (by shutter curtain)

long int SSmicro1;    // Shutter Speed in Microseconds calculated from laser1
long int SSmicro2;    // Shutter Speed in Microseconds calculated from laser2

long int shCurtainspeedMilliS1;  // curtain 1 speed in Milliseconds
long int shCurtainspeedMilliS2;  // curtain 2 speed in Milliseconds
long int shCurtainSpeedMicroS1;  // curtain 1 speed in Microseconds
long int shCurtainSpeedMicroS2;  // curtain 2 speed in Microseconds

float SSmillis1;   // Shutter Speed in Millieseconds
float SSmillis2;   // Shutter Speed in Millieseconds
int SSmillisInt1;  // Shutter Speed in Millieseconds rounded
int SSmillisInt2;  // Shutter Speed in Millieseconds rounded

float SSsec1;  // Shutter Speed in Seconds
float SSsec2;  // Shutter Speed in Seconds

int SSfracV1;  // 1/Shutter Speed Fraction of second rounded
int SSfracV2;  // 1/Shutter Speed Fraction of second rounded

int SSfracAvV1;// 1/Average Shutter Speed Fraction of second rounded
int SSfracAvV2;// 1/Average Shutter Speed Fraction of second rounded

bool firedFlag1;          // flag set when the shutter has been firedFlag1, Laser 1
bool firedFlag2;          // flag set when the shutter has been firedFlag2, Laser 2
bool singleLaserFlag;     // flag set if only one laser being used, calculated in program
bool shutterBounceFlag1;  // flag set if shutter shutterBounce detected.
bool shutterBounceFlag2;  // flag set if shutter shutterBounce detected.
bool sensorReversedFlag;  // flag set is sensors triggered in wrong order

//variables used in ISR
volatile int risingLaser1;       // increases each time isr is called & detects shutter open on  first sensor
volatile int fallingLaser1;      // increases each time isr is called & detects shutter close on first sensor
volatile int risingLaser2;       // increases each time isr is called & detects shutter open on  second sensor
volatile int fallingLaser2;      // increases each time isr is called & detects shutter close on second sensor
volatile bool laserChangeFlag2;  // flag set in isr, set when isr called, used to  determine single laser use


void setup() {  // This part of the program is run exactly once on boot

  SSMILLISAV1.clear();              // clear average counters
  SSMILLISAV2.clear();
  SHCURTAINSPEEDMILLISAV1.clear();
  SHCURTAINSPEEDMILLISAV2.clear();

  //define & setup input pins
  pinMode(2, INPUT);             // Laser 1 input
  pinMode(3, INPUT);             // Laser 2 input
  pinMode(11, INPUT_PULLUP); // average reset button
  pinMode(12, INPUT_PULLUP); // average reset button

  attachInterrupt(digitalPinToInterrupt(2), CLOCK1, CHANGE);  // run the ISR CLOCK1, every time the voltage on pin 2 changes.
  attachInterrupt(digitalPinToInterrupt(3), CLOCK2, CHANGE);  // run the ISR CLOCK2, every time the voltage on pin 3 changes.


  //start serial monitor & output to PC screen
  Serial.begin(115200);

  Serial.println(F("Camera Shutter Tester"));
  Serial.println(F("https://www.photrio.com/forum/threads/build-a-shutter-tester-for-focal-plane-shutters-cheap-easy-it-works.197756/"));

  Serial.println(F("version 3.0.1"));
  Serial.println(F("4 April 2023"));

  // initialize the lcd
  lcd.init();
  lcd.backlight();
  lcd.clear();
  lcd.setCursor(0, 0);
  lcd.print("   Camera Shutter  ");
  lcd.setCursor(0, 1);
  lcd.print("      Tester       ");
  lcd.setCursor(3, 2);
  lcd.print("version 3.0.1");
  lcd.setCursor(3, 3);
  lcd.print("4 April 2023");

  delay(3000);
  lcd.clear();

  lcd.setCursor(0, 0);
  lcd.print(F("Laser2   Laser1     "));
  LCDdisplay();


  clearVars(); // clear all variables & flags - good housekeeping
}  //end void setup



void loop() {  // main program starts here
  // first laser
  if (risingLaser1 == 1) {  // rising count increased in ISR, first laser seen, (shutter opening)
    Start1 = micros();      // set the variable Start1 to current microseconds (detected shutter open)
    risingLaser1++;         // increase rising count, so that this code isn't used again during shutter cycle
  }

  if (fallingLaser1 == 1) {  // falling count increased in ISR, first laser changed to not seen, (shutter closing)
    Stop1 = micros();        // set the variable Stop1 to current microseconds (detected shutter closing)
    fallingLaser1++;         // increase falling count, so that this code isn't used again during shutter cycle
    firedFlag1 = true;       // set the firedFlag1 flag to 1, to allow calculation of shutter speed.
  }

  // second laser
  if (risingLaser2 == 1) {  // rising count increased in ISR, second laser seen, (shutter opening)
    Start2 = micros();      // set the variable Start2 to current microseconds (detected shutter open)
    risingLaser2++;         // increase falling count, so that this code isn't used again during shutter cycle
  }

  if (fallingLaser2 == 1) {  // falling count increased in ISR, first laser changed to not seen, (shutter closing)
    Stop2 = micros();        // set the variable Stop2 to current microseconds (detected shutter closing)
    fallingLaser2++;         // increase the falling flag count, so that this code isn't used again during shutter cycle
    firedFlag2 = true;       // set the firedFlag2 flag, to allow calculation of shutter speed
  }

  if (digitalRead(12) == LOW) { // if reset average button is pushed, go to subroutine
    resetAv();
  }

  if (digitalRead(11) == LOW) { // if display average button is pushed, go to subroutine
    LCDdisplayAv();
    LCDdisplay();
  }

  // if shutter cycle complete, run the subroutines
  if (firedFlag1 == true && firedFlag2 == true) {
    shutterBounceCheck();
    processData();
    altDisplay ();
    LCDdisplay();
    clearVars();
  }

  // if only 1 laser has operated,after 1 second, invoke single laser mode.
  else if (firedFlag1 == true && laserChangeFlag2 == false && (micros() - Stop1 >= 1000000)) {
    singleLaserFlag = true;
    shutterBounceCheck();
    processData();
    altDisplay ();
    LCDdisplay();
    clearVars();
  }
}  // jump back to void loop



// Subrouties.

void shutterBounceCheck() {  // wait for a while to see if shutter bounces open, second laser
  for (uint32_t tStart = millis(); (millis() - tStart) < 1000;) { // sit in a loop, to see if a bounce occurs
    if (risingLaser2 > 2) { // check to see if ISR has recorded sensor activations
      shutterBounceFlag2 = true;
    }
  }

  if (risingLaser1 > 2) { // check to see if ISR has recorded sensor activations on first laser
    shutterBounceFlag1 = true;
  }
} // end_shutterBounceCheck



//  Do the maths
void processData() {

  if ((Start2 < Start1) || (Stop2 < Stop1)) {  // error check lasers triggered in reverse (subtraction for micro-wrap)
    sensorReversedFlag = true;
  }
  else {
    sensorReversedFlag = false;
  }

  // do the maths calculations for first laser
  SSmicro1 = (Stop1 - Start1);             // calculate shutter open/close in microseconds
  SSmillis1 = (Stop1 - Start1) / 1000.0;   // calculate shutter open/close in millieseconds
  SSmillisInt1 = (int(SSmillis1 + 0.5));   // convert millis1 to rounded int
  SSsec1 = (float)SSmicro1 / 1000000.0;    // convert shutter SSmicro1 to seconds
  SSfracV1 = (1.0 / SSsec1) + 0.5;         // inverse of theSSsec1, to give vulgar fraction rounded

  // do the maths calculations for second laser
  if (singleLaserFlag == false) {           // do the maths for shutter curtain speed if two lasers used
    SSmicro2 = (Stop2 - Start2);            // calculate shutter open/close in microseconds
    SSmillis2 = (Stop2 - Start2) / 1000.0;  // calculate shutter open/close in millieseconds
    SSmillisInt2 = (int(SSmillis2 + 0.5));  // convert millis2 to rounded int
    SSsec2 = (float)SSmicro2 / 1000000.0;   // convert shutter SSmicro2 to seconds
    SSfracV2 = (1.0 / SSsec2) + 0.5;        // inverse of theSSsec2, to give vulgar fraction rounded



    // do the maths for shutter curtain speed as two lasers used
    shCurtainSpeedMicroS1 = (Start2 - Start1);         // Microseconds
    shCurtainSpeedMicroS2 = (Stop2  - Stop1);          // Microseconds
    shCurtainspeedMilliS1 = (Start2 - Start1) / 1000;  // miliseconds
    shCurtainspeedMilliS2 = (Stop2  - Stop1)  / 1000;  // miliseconds
  }

  else {  // clear second laser vars as not used
    SSmicro2 = 0;
    SSmillis2 = 0;
    SSmillisInt2 = 0;
    SSsec2 = 0;
    SSfracV2 = 0;
    //String StringFracV2 = "0";
  }


  // Shutter speed average
  SSMILLISAV1.addValue(SSmillisInt1);                    // add last readings to aveerage

  // shutter curtain average
  if (singleLaserFlag == false && sensorReversedFlag == false) {  // only calc if possible
    SSMILLISAV2.addValue(SSmillisInt2);                           // add last readings to average
    SHCURTAINSPEEDMILLISAV1.addValue(shCurtainspeedMilliS1);      // add last readings to aveerage
    SHCURTAINSPEEDMILLISAV2.addValue(shCurtainspeedMilliS2);      // add last readings to aveerage
  }

  // format shutter1 average to vulgar fraction
  float calc1;
  calc1 = (float)SSMILLISAV1.getAverage() / 1000.0;   // convert shutter1 average mS to seconds
  SSfracAvV1 = int (1.0 / calc1 + 0.5);               // inverse to give vulgar fraction rounded

  calc1 = (float)SSMILLISAV2.getAverage() / 1000.0;   // convert shutter1 average mS to seconds
  SSfracAvV2 = int ((1.0 / calc1) + 0.5);             // inverse to give vulgar fraction rounded
}  // end_processData




// print to screen in tabulated output, neater & easier to read
void altDisplay() {

  String StringFrac     = "1/";     // symbol used for vulgar fraction
  String StringFracV1   = StringFrac + String(SSfracV1);   // make a string for neat printing. Laser 1 shutter speed vulgar fraction
  String StringFracV2   = StringFrac + String(SSfracV2);   // make a string for neat printing. Laser 2 shutter speed vulgar fraction
  String StringFracAvV1 = StringFrac + String(SSfracAvV1); // make a string for neat printing. Laser 1 Av shutter speed vulgar fraction
  String StringFracAvV2 = StringFrac + String(SSfracAvV2); // make a string for neat printing. Laser 2 Av shutter speed vulgar fraction

  // print shutter speed.Ms, mS, S
  Serial.println(F(" PARAMETER                  LASER2           LASER1"));
  printf(" Shutter Speed MicroS   %10lu       %10lu \n", SSmicro2, SSmicro1);
  printf(" Shutter Speed milliS   %10i       %10i \n\n", SSmillisInt2, SSmillisInt1);
  printf(" Shutter Speed Seconds     %7.3f          %7.3f \n", SSsec2, SSsec1);

  Serial.print(F(" Shutter Speed Fraction "));
  if (SSsec2 < 1 && singleLaserFlag == false) {   // test if Laser2 less than 1 second, if so, print in fractions
    printf("%10s", StringFracV2.c_str());         // display shutter SSMs in fractions
  }
  else {
    printf("          ");
  }

  if (SSsec1 < 1) {   // test if Laser1 less than 1 second, if so, print vulgar fraction
    printf("       %10s \n\n", StringFracV1.c_str());
  }
  else {
    printf("\n\n");
  }

  // print curtain speeds
  if (singleLaserFlag == false && sensorReversedFlag == false) {
    printf(" Curtain Travel MicroS  %10li       %10li \n",   shCurtainSpeedMicroS2, shCurtainSpeedMicroS1);
    printf(" Curtain Travel MilliS  %10li       %10li \n\n", shCurtainspeedMilliS2, shCurtainspeedMilliS1);
  }


  // print averages
  Serial.println(F(" AVERAGES                    LASER2           LASER1"));

  printf(" shutter Speed  Av mS %2i %10.0f       %10.0f \n",    SSMILLISAV1.getCount(), SSMILLISAV2.getAverage() , SSMILLISAV1.getAverage() );
  printf(" Curtain Travel Av mS %2i %10.0f       %10.0f \n\n",  SHCURTAINSPEEDMILLISAV1.getCount(), SHCURTAINSPEEDMILLISAV2.getAverage(), SHCURTAINSPEEDMILLISAV1.getAverage() );


  // print shutter averages as vulgar fraction, if less than 1
  printf(" Shutter Speed Av Vul %2i", SSMILLISAV1.getCount() );

  if (SSfracAvV2 > 1) {
    printf(" %10s",  StringFracAvV2.c_str() );
  }
  else printf("   %8.2f", SSMILLISAV2.getAverage() / 1000 );

  if (SSfracAvV1 > 1) {
    printf("       %10s \n\n", StringFracAvV1.c_str() );
  }
  else printf("         %8.2f \n\n", SSMILLISAV1.getAverage() / 1000 );

  // print Min, Max & SD
  printf(" shutter Speed Min mS %2i %10.0f       %10.0f \n",    SSMILLISAV1.getCount(), SSMILLISAV2.getMin(), SSMILLISAV1.getMin() );
  printf(" shutter Speed Max mS %2i %10.0f       %10.0f \n\n",  SSMILLISAV1.getCount(), SSMILLISAV2.getMax(), SSMILLISAV1.getMax() );

  printf(" shutter Speed  St Dev%2i  %9.2f         %9.2f \n",   SSMILLISAV1.getCount(), SSMILLISAV2.getStandardDeviation(), SSMILLISAV1.getStandardDeviation() );
  printf(" Curtain Travel St Dev%2i  %9.2f         %9.2f \n\n", SHCURTAINSPEEDMILLISAV1.getCount(), SHCURTAINSPEEDMILLISAV2.getStandardDeviation(), SHCURTAINSPEEDMILLISAV2.getStandardDeviation() );

  // print  warnings
  if (shutterBounceFlag2 == true) {       // print shutter 2 bounce count.
    printf(" Second curtain Bounce(s)!  %i \n", risingLaser2 - 2 );
  }

  if (shutterBounceFlag1 == true) {      // print shutter 1 bounce count.
    printf(" First curtain Bounce(s)!  %i \n", risingLaser1 - 2 );
  }

  if (singleLaserFlag == false && sensorReversedFlag == true) { // print warning
    //printf("Sensor or camera is reversed. Unable to calculate curtain speed \n");
    Serial.println(F(" Sensor or camera is reversed. Unable to calculate curtain speed"));
  }

  if (Start2 < Stop1 && sensorReversedFlag == false) {
    //printf("Flash Sync (between the two lasers)\n");
    Serial.println(F(" Flash Sync (between the two lasers)"));
  }

  printf("\n");
}// end_void altDisplay



// output to LCD
void LCDdisplay() {

  // print 'Bou' on line 0 if shutter bounce detected
  if (shutterBounceFlag2 == true || shutterBounceFlag1 == true) {
    lcd.setCursor(17, 0);
    lcd.print("Bou");
  } else {
    lcd.setCursor(17, 0);
    lcd.print("   ");
  }

  // print miliseconds on line 1 (lines numbered 0, 1, 2, 3)
  lcd.setCursor(0, 1);
  lcd.print("                  ");

  lcd.setCursor(9, 1);    // print var 1 on right pos 9
  lcd.print(SSmillisInt1);

  lcd.setCursor(0, 1);    // print var 2 on left pos 0
  lcd.print(SSmillisInt2);

  lcd.setCursor(18, 1);   // print unit
  lcd.print("mS");

  // print mS or vulgar fraction on line 2
  lcd.setCursor(0, 2);
  lcd.print("                  ");

  if (SSsec1 < 1) {  // if first laser measurement is < 1 second, print as fraction
    lcd.setCursor(9, 2);  // print var 1 on right pos 9
    lcd.print("1/");
    lcd.print(SSfracV1);
  }

  else {
    lcd.setCursor(9, 2); // print var 1 on right pos 9
    lcd.print(SSsec1);
  }

  lcd.setCursor(18, 2); // print unit
  lcd.print(" S");


  // print mS or vulgar fraction
  if (SSsec2 < 1 && singleLaserFlag == false) {  // if second laser measurement is < 1 second, print as fraction
    lcd.setCursor(0, 2);  // print var 2 on left pos 9
    lcd.print("1/");
    lcd.print(SSfracV2);
  } else {
    lcd.setCursor(0, 2);  // print var 2 on left pos 0
    lcd.print(SSsec2);
  }


  // print curtain speed on line 3,
  if (sensorReversedFlag == false) {
    lcd.setCursor(0, 3);
    lcd.print("                  ");

    lcd.setCursor(9, 3);  // print var 1 on right pos 9
    lcd.print("C2 ");
    lcd.print(shCurtainspeedMilliS1);

    lcd.setCursor(0, 3);  // print var 2 on left pos 0
    lcd.print("C1 ");
    lcd.print(shCurtainspeedMilliS2);

    lcd.setCursor(18, 3); // print unit
    lcd.print("mS");
  }
  else {
    lcd.setCursor(0, 3);
    lcd.print("Unable to calc CuSpd");
  }
}  // end_LCDdisplay


void LCDdisplayAv() {
  detachInterrupt(digitalPinToInterrupt(2));  // detatch ISR CLOCK1,
  detachInterrupt(digitalPinToInterrupt(3));  // detatch ISR CLOCK2,

  // print header
  lcd.setCursor(0, 0);
  lcd.print(F("Averge2  Average1   "));


  // diaplay shutter speed averages mS
  lcd.setCursor(0, 1);
  lcd.print("                  ");

  lcd.setCursor(9, 1);    // print var 1 on right pos 9
  lcd.print(int(SSMILLISAV1.getAverage()));

  lcd.setCursor(0, 1);   // print var 2 on left pos 0
  lcd.print(int(SSMILLISAV2.getAverage()));

  lcd.setCursor(18, 1);
  lcd.print("mS");


  // display SS1 average as vulgar or decimal fraction
  lcd.setCursor(0, 2);
  lcd.print("                  ");

  lcd.setCursor(9, 2);  // print var 1 on right pos 9
  if (SSfracAvV1 > 1 ) {  // print vugar
    lcd.print("1/");
    lcd.print(SSfracAvV1);
  }
  else {                  // or print decimal
    lcd.print(SSMILLISAV1.getAverage() / 1000);
  }

  // display SS2 average as vulgar or fraction
  lcd.setCursor(0, 2);  // print var 2 on left pos 0
  if (SSfracAvV2 > 1 ) {
    lcd.print("1/");
    lcd.print(SSfracAvV2);
  }
  else {                  // or print decimal
    lcd.print(SSMILLISAV2.getAverage() / 1000 );
  }
  lcd.setCursor(18, 2); // print unit
  lcd.print(" S");


  // diaplay curtain speed averages
  lcd.setCursor(0, 3);
  lcd.print("                  ");

  lcd.setCursor(9, 3); // print var 1 on right pos 9
  lcd.print("C2 ");
  lcd.print(int(SHCURTAINSPEEDMILLISAV1.getAverage()));

  lcd.setCursor(0, 3);  // print var 2 on left pos 0
  lcd.print("C1 ");
  lcd.print(int(SHCURTAINSPEEDMILLISAV2.getAverage()));

  lcd.setCursor(18, 3);   // print unit
  lcd.print("mS");

  while (digitalRead(11) == LOW) {} // wait for button release
  delay(250);                       // short delay for bounce
  lcd.setCursor(0, 0);              // print header
  lcd.print(F("Laser2   Laser1     "));

  EIFR = 3;
  attachInterrupt(digitalPinToInterrupt(2), CLOCK1, CHANGE);  // run the ISR CLOCK1, every time the voltage on pin 2 changes.
  attachInterrupt(digitalPinToInterrupt(3), CLOCK2, CHANGE);  // run the ISR CLOCK2, every time the voltage on pin 3 changes.
} // end_LCDdisplayAV


void resetAv() {
  detachInterrupt(digitalPinToInterrupt(2));  // detatch the ISR CLOCK1
  detachInterrupt(digitalPinToInterrupt(3));  // detatch the ISR CLOCK2

  Serial.println(F("Reset Average"));
  SSMILLISAV1.clear();              // clear average counters
  SSMILLISAV2.clear();
  SHCURTAINSPEEDMILLISAV1.clear();
  SHCURTAINSPEEDMILLISAV2.clear();

  while (digitalRead(12) == LOW) {} // wait for button release
  delay(250);                       // short delay for bounce

  EIFR = 3;
  attachInterrupt(digitalPinToInterrupt(2), CLOCK1, CHANGE);  // run the ISR CLOCK1, every time the voltage on pin 2 changes.
  attachInterrupt(digitalPinToInterrupt(3), CLOCK2, CHANGE);  // run the ISR CLOCK2, every time the voltage on pin 3 changes.

} //end_resetAV


// clear vars
void clearVars() {
  noInterrupts();
  Start1 = 0;
  Stop1 = 0;
  Start2 = 0;
  Stop2 = 0;

  SSmicro1 = 0;
  SSmicro2 = 0;

  //  shCurtainspeedMilliS1 = 0;
  //  shCurtainspeedMilliS2 = 0;
  shCurtainSpeedMicroS1 = 0;
  shCurtainSpeedMicroS2 = 0;

  SSmillis1 = 0;
  SSmillis2 = 0;
  //  SSmillisInt1 = 0;
  //  SSmillisInt2 = 0;

  //  SSsec1 = 0;
  //  SSsec2 = 0;

  //  SSfracV1 = 0;
  //  SSfracV2 = 0;

  String StringFracV1 = "0";
  String StringFracV2 = "0";

  firedFlag1 = false;
  firedFlag2 = false;
  singleLaserFlag = false;

  risingLaser1 = 0;
  risingLaser2 = 0;
  fallingLaser1 = 0;
  fallingLaser2 = 0;
  laserChangeFlag2 = false;
  shutterBounceFlag1 = false;
  shutterBounceFlag2 = false;
  sensorReversedFlag = false;

  EIFR = bit(INTF0);
  EIFR = bit(INTF1);
  interrupts();
}  // end_clearVars



//    Interrupt Routines
void CLOCK1() {  // interrupt called everytime the voltage on pin 2 changes, laser 1,
  if (digitalRead(2) == seen) {
    risingLaser1++;
  } // if the voltage on pin 2 is high, increase rising count.

  if (digitalRead(2) == blocked) {
    fallingLaser1++;
  } // If the voltage on pin 2 is low, increase falling count
} // end_ISR


void CLOCK2() {  // interrupt called everytime the voltage on pin 3 changes
  if (digitalRead(3) == seen) {
    risingLaser2++;           // if the voltage on pin 3 is high, increase rising count
    laserChangeFlag2 = true;  // set flag
  }
  if (digitalRead(3) == blocked) {
    fallingLaser2 = true;
  } // If the voltage on pin 3 is low, increase falling count
} // end_ISR

// end ISR
