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