Contador-restador

Aquí el código que propongo:

#include <LiquidCrystal_I2C.h>

LiquidCrystal lcd(12, 11, 5, 4, 3, 2); // Declaramos los pines que usa nuestra pantalla(RS,E,D4,D5,D6,D7)

// Definición de los pines a las que se conectan las dos LDR que han de detectar el laser
// (si la cuenta "al revés" se han de intercambiar los pines en la definición)
const int SENSOR_PIN_A = 2; // Pin al que se conecta una de las dos LDR
const int SENSOR_PIN_B = 3; // Pin al que se conecta otra de las dos LDR

static const bool VALOR_DETECCION = LOW; // Valor que se lee cuando se interrumpe el laser sobre los LDR

// Declaración de la clase que se encarga de controlar las dos LDR
class SensorDePaso {
  public:
    SensorDePaso() : estado(ESTADO_REPOSO), valor(0) {};
    void setA(boolean detecta);
    void setB(boolean detecta);
    int getValor() {return this->valor;};
    void setValor(int nuevoValor) {this->valor = nuevoValor;};
  private:
    enum estado_t {
      ESTADO_REPOSO,
      ESTADO_A,
      ESTADO_A_B,
      ESTADO_A_B_A,
      ESTADO_B,
      ESTADO_B_A,
      ESTADO_B_A_B
    };
    volatile estado_t estado;
    volatile int valor;
};

// Función de la clase que se ha de llamar cuando hay un cambio de valor en una de las LDR
void SensorDePaso::setA(boolean detecta) {
  if (detecta == VALOR_DETECCION) {
    switch (this->estado) {
      case ESTADO_REPOSO :
        this->estado = ESTADO_A;
        break;
      case ESTADO_A :
        // No hace nada
        break;
      case ESTADO_A_B :
        // No hace nada
        break;
      case ESTADO_A_B_A :
        this->estado = ESTADO_A_B;
        break;
      case ESTADO_B :
        this->estado = ESTADO_B_A;
        break;
      case ESTADO_B_A :
        // No hace nada
        break;
      case ESTADO_B_A_B :
        // No hace nada
        break;
    }
  }
  else {
    switch (this->estado) {
      case ESTADO_REPOSO :
        // No hace nada
        break;
      case ESTADO_A :
        this->estado = ESTADO_REPOSO;
        break;
      case ESTADO_A_B :
        this->estado = ESTADO_A_B_A;
        break;
      case ESTADO_A_B_A :
        // No hace nada
        break;
      case ESTADO_B :
        // No hace nada
        break;
      case ESTADO_B_A :
        this->estado = ESTADO_A;
        break;
      case ESTADO_B_A_B :
        this->estado = ESTADO_REPOSO;
        this->valor++;
        break;
    }
  }
}

// Función de la clase que se ha de llamar cuando hay un cambio de valor en una de las LDR
void SensorDePaso::setB(boolean detecta) {
  if (detecta == VALOR_DETECCION) {
    switch (this->estado) {
      case ESTADO_REPOSO :
        this->estado = ESTADO_B;
        break;
      case ESTADO_B :
        // No hace nada
        break;
      case ESTADO_B_A :
        // No hace nada
        break;
      case ESTADO_B_A_B :
        this->estado = ESTADO_B_A;
        break;
      case ESTADO_A :
        this->estado = ESTADO_A_B;
        break;
      case ESTADO_A_B :
        // No hace nada
        break;
      case ESTADO_A_B_A :
        // No hace nada
        break;
    }
  }
  else {
    switch (this->estado) {
      case ESTADO_REPOSO :
        // No hace nada
        break;
      case ESTADO_B :
        this->estado = ESTADO_REPOSO;
        break;
      case ESTADO_B_A :
        this->estado = ESTADO_B_A_B;
        break;
      case ESTADO_B_A_B :
        // No hace nada
        break;
      case ESTADO_A :
        // No hace nada
        break;
      case ESTADO_A_B :
        this->estado = ESTADO_B;
        break;
      case ESTADO_A_B_A :
        this->estado = ESTADO_REPOSO;
        this->valor--;
        break;
    }
  }
}

// Objeto gloval que se encarga de controlar la detección
SensorDePaso sensorDePaso;

// Interrupción que se ejecuta al cambiar de valor el pin que lee el estado de una de las LDR
void interruptCountA() {
  sensorDePaso.setA(digitalRead(SENSOR_PIN_A));
}

// Interrupción que se ejecuta al cambiar de valor el pin que lee el estado de una de las LDR
void interruptCountB() {
  sensorDePaso.setB(digitalRead(SENSOR_PIN_B));
}

int contador = 0; // Variable auxiliar que nos ayuda a saber si hay cambios en el conteo

void setup() {
  // Configuramos los pines como entrada
  pinMode(SENSOR_PIN_A, INPUT);
  pinMode(SENSOR_PIN_B, INPUT);
  // Asociamos las interrupciones de ambos pines a las funciones
  attachInterrupt(digitalPinToInterrupt(SENSOR_PIN_A), interruptCountA, CHANGE);
  attachInterrupt(digitalPinToInterrupt(SENSOR_PIN_B), interruptCountB, CHANGE);

  lcd.begin(16, 2); //Iniciamos la pantalla y le decimos el numero de caracteres y filas
  lcd.setCursor(0, 0);
  lcd.print(F("BARRERA LASER"));
  lcd.setCursor(0, 1);
  lcd.print(F("CONTADOR: 0"));
}

void loop() {
  if (contador != sensorDePaso.getValor()) {  // Si el valor que teníamos es diferente al que ha detectado...
    contador = sensorDePaso.getValor();       // ... obtenemos el valor actual
    if (contador < -3) {                      // Si el valor actual es menor que -3 (esto es para demostras cómo se puede establecer el valor)
      contador = 0;                           // Ponemos a cero "nuestro contador"
      sensorDePaso.setValor(contador);        // Establecemos el valor del controlador
    }
    lcd.setCursor(10, 1);
    lcd.print(contador);  // Mostramos el valor del contador actualizado
    lcd.print(' ');       // Este espacio es para cuando pasamos a mostar un dígito menos. Por ejemplo: de 10 a 9, para que no se vea 90 (el espacio "tapa" el cero del 10)
  }
}