Contador-restador

Buen dia

me podrian ayudar con un proyecto en el que trabajo, en esta parte al presionar A0 suma y al presionar A1 resta, estoy un poco oxidado al programar y agradezco cualquier idea que tengan,dejo la simulacion en proteus por si gustan checar el funcionamiento.

Gracias por su tiempo :slight_smile:

// incluir libreria
#include <LiquidCrystal.h>

//Declaramos las variables necesarias
int numero=0;
int auxnumero=0;
int auxnumero1=0;
int sensorPinLDR = A0;
int sensorPinLDR1 = A1;
int valorLDR = 0;
int valorLDR1 = 0;


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

void setup() {
  
  lcd.begin(16, 2);//Iniciamos la pantalla y le decimos el numero de caracteres y filas
  
  
  lcd.setCursor(3, 1);
  lcd.print("BARRERA LASER");
  delay (300);
  lcd.clear();
  
  
}

void loop() {
      valorLDR = analogRead(sensorPinLDR);// Leemos el valor de la LDR y lo guardamos en valorLDR
  valorLDR1 = analogRead(sensorPinLDR1);// Leemos el valor de la LDR y lo guardamos en valorLDR
  lcd.setCursor(0, 0);//Situamos el lugar donde escribiremos
  lcd.print("CONTADOR");//Escribimos contador
  lcd.setCursor(10, 1);//Situamos el lugar donde escribiremos
  lcd.print(numero);//Representamos la variable numero
  
  auxnumero=0;//hacemos la variable auxnumero 0. Esta variable nos ayuda a contar solo 1 cada vez que entremos en el bucle de más abajo

switch (numero) {
  case 0:
   while(valorLDR<50){//Entramos en el bucle si valorLDR es menor de 50. Esto ocurre cuando no da el laser sobre la LDR.
    valorLDR = analogRead(sensorPinLDR);// Leemos el valor de la LDR y lo guardamos en valorLDR
    if(auxnumero==0){// Entramos en el if si auxnumero es 0. Esto solo ocurre la primera vez que recorremos el while.
    numero++;//Sumamos 1 a la variable numero
    auxnumero=1;//hacemos auxnumero 1, para que solo sume una vez 1 a la variable numero cuando estamos dando vueltas dentro del bucle.
      }
    }  
   
  case 1:
     while(valorLDR1<50){//Entramos en el bucle si valorLDR1 es menor de 50. Esto ocurre cuando no da el laser sobre la LDR.
    valorLDR1 = analogRead(sensorPinLDR1);// Leemos el valor de la LDR y lo guardamos en valorLDR
    if(auxnumero1!=0){// Entramos en el if si auxnumero es diferente a 0. Esto solo ocurre la primera vez que recorremos el while.
    numero--;//resta 1 a la variable numero
    auxnumero1=1;//hacemos auxnumero 1, para que solo resta una vez 1 a la variable numero cuando estamos dando vueltas dentro del bucle.
    }
      }
}

    }

contador-restador.zip (21.7 KB)

Hola RaulRD. Tengo un problema con tu consulta. No s√© ex√°ctamente qu√© es lo que quieres hacer y para qu√©. No aportas mucha informaci√≥n. As√≠ que como no tengo ni idea, soy ignorante en cuanto a tu prop√≥sito, me he montado mi propia pel√≠cula y me he supuesto que quieres contabilizar la gente que entra y sale de un lugar. Y para ello usas una barrera de uno o dos l√°seres que apuntan a dos LDR y al ser interrumpido por el paso de las personas, primero uno y despu√©s otro, sabes si entran o salen. Si entran supongo que sumas uno y si salen restas uno, con lo que obtienes en todo momento la cantidad de gente que ‚Äúse supone‚ÄĚ que hay en ese lugar.

Lo dicho, esa es la película que me he montado y el problema que me he imaginado que tratas de abordar. Si no es ese, espero que sea algo parecido y que mi propuesta te valga.

A parte del problema de que te entren o salgan dos o m√°s personas juntas y la barrera lo detecte como una sola, tambi√©n est√° el problema que primero sea detectado un brazo o cualquier otra cosa y luego el cuerpo de la persona, con lo que contar√≠a como dos y no como uno. Este √ļltimo problema se podr√≠a atenuar si las dos LDR est√°n separadas entre s√≠ ‚Äúcasi un cuerpo‚ÄĚ de distancia, porque si no se activan las dos a la vez es porque el obst√°culo era menor que un cuerpo. O si se ponen las dos LDR juntas se podr√≠a calcular cu√°nto tiempo tarda ‚Äúel obst√°culo‚ÄĚ en pasar y si es menor que un tiempo dado asumir que es un brazo o cualquier otra cosa ‚Äúpeque√Īa‚ÄĚ y descartarla. El problema es que la gente pase corriendo y el tiempo que obstaculiza el l√°ser sea muy corto.

Yo para las pruebas he puesto las dos LDR una junto a la otra, pegadas. Iluminadas por un √ļnico puntero l√°ser (un que tengo de esos ‚Äúkits de sensores y cachivaches Arduinos‚ÄĚ que venden los chinos). A pesar de tener las dos LDR juntas, el √ļnico l√°ser que tengo a penas iluminaba la tercera parte de cada una, as√≠ que le he puesto en frente del l√°ser, ‚Äúpegado a √©l‚ÄĚ, una bolsita de pl√°stico transparente para que lo disperse y as√≠ ilumina poco m√°s de la mitad de cada una y parece que la cosa va mejor.

A parte de ponerlas juntas y usar un √ļnico puntero l√°ser ‚Äúdispersado‚ÄĚ, a diferencia de lo que t√ļ haces, no las he conectado a las entradas anal√≥gicas para hacer lecturas anal√≥gicas. Las he conectado a dos entradas digitales para hacer lecturas digitales. En las entradas digitales por encima de un voltaje lo considera un ‚Äúnivel alto‚ÄĚ y por debajo de ese un ‚Äúnivel bajo‚ÄĚ. As√≠ que he conectado las LDR cada una con dos resistencias de 220 ohmios en serie (no encontr√© resistencias de alrededor de 400 ohmios como quer√≠a, as√≠ que las dos en serie de 220 son 440 ohmios). A cada pin de entrada le conect√© una LDR a 5V y las dos resistencias de 220 ohmios en serie a GND. He de aclarar que ‚Äúel experimento‚ÄĚ lo he hecho con un Arduino UNO que funciona a 5 voltios. A groso modo algo tal que as√≠:

  5V -----+
          |
         LDR
          |
  PIN ----+
          |
         220
          |
         220
          |
  GND ----+

Si se tienen resistencias de aproximadamente 400 ohmios sería mejor, ya que basta una por cada LDR, yo lo he hecho con lo que tenía a mano. Las de 220 ohmios son las que se suelen poner en serie a los LED. Tampoco has dicho cómo tienes hecho el montaje. Y probablemente las resistencias que tengas te valgan.

El caso es que al haberlo montado con las LDR conectadas a los 5 voltios, en mi caso, cuando se obstaculiza el láser lo que se lee en el pin es un nivel bajo (LOW). Así que, por si en tu caso resultara ser al revés y que por tener las LDR conectadas a masa, bastaría con cambiar la definición de las constante VALOR_DETECCION a el valor HIGH, tal que quedara así:

static const bool VALOR_DETECCION = HIGH; // Valor que se lee cuando se interrumpe el l√°ser sobre los LDR

Esto es importante, porque si no tiene el valor correcto la cosa no funciona.

Otra cosa importante es que como las LDR se pueden juntas, la diferencia de tiempo en que se ‚Äúactivan‚ÄĚ o ‚Äúdesactivan‚ÄĚ las dos puede llegar a ser muy corto y si no se lee con suficiente rapidez no se puede averiguar en qu√© sentido ha pasado la persona. Por eso es por lo que he usado las interrupciones del Arduino UNO. √Čste s√≥lo tiene dos pines que se puedan controlar ‚Äúf√°cilmente‚ÄĚ desde la plataforma Arduino. Los pines 2 y 3. As√≠ que si tienes un Arduino UNO has de usar esos dos. Si tienes un Arduino que pueda trabajar con interrupciones con otros pines y quieres usar esos otros, s√≥lo has de cambiar las constantes que lo definen.

As√≠ que las dos LDR las has de conectar a los pines 2 y 3 del Arduino. Si por un casual te ‚Äúcuenta al rev√©s‚ÄĚ y decrementa cuando debiera incrementar y viceversa, basta con que intercambies los valores en la definici√≥n de las dos constantes y vuelvas a subir el programa al Arduino (o que intercambies los dos cables de ambos pines, lo que te sea m√°s f√°cil).

A modo de ejemplo he puesto que si llega a contar por debajo de menos tres, ponga el contador a cero. Me imagino que en todo caso interesará que se ponga a cero en cuanto de un valor negativo o si se pulsa un botón para resetearlo.

La soluci√≥n que he puesto pasa por usar una m√°quina de estados para controlar el orden en que se obstaculizan las LDR y saber en qu√© sentido pasa la persona. Es importante que si se van a poner las LDR separadas, no sea muy grande la separaci√≥n, ya que han de estar en alg√ļn momento las dos "bloqueadas" a la vez para que el la detecci√≥n funcione correctamente. Si no se llegan a bloquear las dos a la vez no se detecta ning√ļn paso.

Lo dicho, esto es una propuesta que te hago en base a lo que me he imaginado que querías hacer. Que lo más probable es que se trate de otra cosa.

Adjunto la propuesta en el siguiente post ya que se pueden en este por ser muy grande el parloteo que he puesto.

Recuerda, se han de conectar las LDR a los pines 2 y 3 del Arduino UNO. Cualquier consulta o duda hacerla en el foro, nada de privados.

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

Buen dia

Me ayudan con un código en el cual trato que sea un contador-restador manejado con botones, el problema empieza cuando integre el restador en el switch, pero con el puro sumador funciona bien, si gustan probarlo lo simulo con proteus agradezco todas las sugerencias.

Gracias!!!

// incluir libreria
#include <LiquidCrystal.h>

//Declaramos las variables necesarias
int numero=0;
int auxnumero=0;
int auxnumero1=0;
int sensorPin = A0;
int sensorPin1 = A1;
int valor = 0;
int valor1 = 0;


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

void setup() {
  
  lcd.begin(16, 2);//Iniciamos la pantalla y le decimos el numero de caracteres y filas
  
  
  lcd.setCursor(3, 1);
  lcd.print("Buen dia");
  delay (300);
  lcd.clear();
  
  
}

void loop() {
      valor = analogRead(sensorPin);// Leemos el valor y lo guardamos en valor
  valor1 = analogRead(sensorPin1);// Leemos el valor  y lo guardamos en valor1
  lcd.setCursor(0, 0);//Situamos el lugar donde escribiremos
  lcd.print("CONTADOR");//Escribimos contador
  lcd.setCursor(10, 1);//Situamos el lugar donde escribiremos
  lcd.print(numero);//Representamos la variable numero
  
  auxnumero=0;//hacemos la variable auxnumero 0. Esta variable nos ayuda a contar solo 1 cada vez que entremos en el bucle de más abajo
  auxnumero1=0;
switch (numero) {
  
  case 0:
   while(valor<50){//Entramos en el bucle si valor es menor de 50.
    valor = analogRead(sensorPin);// Leemos el valor
    if(auxnumero==0){// Entramos en el if si auxnumero es 0. Esto solo ocurre la primera vez que recorremos el while.
    numero++;//Sumamos 1 a la variable numero
    auxnumero=1;//hacemos auxnumero 1, para que solo sume una vez 1 a la variable numero cuando estamos dando vueltas dentro del bucle.
      }
    }  
   
  case 1:
     while(valor1<50){//Entramos en el bucle si valor1 es menor de 50.
    valor1 = analogRead(sensorPin1);// Leemos el valor1 y lo guardamos en valor1
    if(auxnumero1==0){// Entramos en el if si auxnumero es diferente a 0. Esto solo ocurre la primera vez que recorremos el while.
    numero--;//resta 1 a la variable numero
    auxnumero1=1;//hacemos auxnumero 1, para que solo resta una vez 1 a la variable numero cuando estamos dando vueltas dentro del bucle.
    }
      } 
}
    }

1.2.ino (2.05 KB)

contador-restador.zip (21.7 KB)

1.2.ino (2.05 KB)

contador-restador.zip (21.7 KB)

Buen día
Seg√ļn entend√≠ quieres que con un bot√≥n suba el contador y con otro baje, tu c√≥digo es muy confuso, no entiendo para que usas un sw-case y dentro de √©ste pones un while(), ademas no entiendo porque usas analogRead() en lugar de digitalRead() para ver el estado de los botones
Prueba el siguiente codigo:

//
 Codigo eliminado por doble post

Al parecer por lo que vi en tu c√≥digo tienes configurados los botones como pull-up, entonces as√≠ quedo el c√≥digo modificado, si no lo tienes as√≠, solo cambia la conexi√≥n de los botones colocando un pin del bot√≥n a tierra y el otro al puerto A0 o A1 seg√ļn corresponda

Buen dia

Gracias IgnoranteAbsoluto por tu gran respuesta, tienes mucha razón en el proyecto que quiero hacer y me impresiona tu sentido de razonamiento, en el que trabajare toda la noche, con todas las bases que me has propuesto, tomare con cuidado el paso en las 2 direcciones.

solo como referencias futuras estoy trabajando con un arduino mega y lo integro en una base de datos en mysql

Gracias por tu tiempo muy valioso, espero en un futuro ayudar también, excelente día

Vaya! ahora me doy cuenta que tienes otro post con la misma consulta
https://forum.arduino.cc/index.php?topic=631807.0 donde ya te contestaron, creo que perdí mi tiempo
No se si eso cuenta como doble post, porque utilizaste otra cuenta, pero esta muy claro que eres la misma persona ya que el código es exactamente el mismo

Bueno no se si banear a ambos Ramian y RaulRD porque ambos o son compa√Īeros de la misma clase o son la misma persona. Cosa que ya determinar√©.
No se pueden abrir dos hilos del mismo tema y menos con diferentes nicks.
Como a√ļn no tengo pruebas lo dejo en stand by pero he unido los hilos.
A ambos por ahora lean las normas del foro, 1er hilo de cualquier sección o idioma.
Acoto, son la misma persona, una cuenta creada con gmail y la otra con outlook.

Buen dia

disculpen por la molestia IgnoranteAbsoluto,RIG y surbyte, tienen razón yo hice la pregunta con otra cuenta, pero como me la hachearon ya no pude entrar en ninguna parte con ese correo y no supe que hacer, aprecio su tiempo y me siento mal si los ofendí a todos, no era mi intención hacerlo, pero si me atengo a las consecuencias, si es su decisión sacarme del foro lo comprendo y agradezco la atención que me ofrecieron.

solo espero su comprencion y apoyo que tengan un excelente día.

como me la hachearon

Que quiere decir?

Ninguna hilo se borra a menos que este duplicado o sea irrespetuoso.

Si la pregunta fue hecha en un sitio, y la muevo a otra Sección como suelo hacer (preguntas del foro General que envío a Software o Hardware) dejo un link para que puedas ir al nuevo lugar.

No hay forma de que no la encuentres
De ultima, vas a tu perfil y cuando ves tus post puedes observar donde esta cada uno y todos los hilos abiertos y pendientes que tienes.

Si vas a tu perfil (Profile) => Forum settings Edit => veras algo como esto

Show Post
Show Draft
etc
etc
etc

En SHow Post estan todas tus intervenciones.

Ahora sigamos con tu hilo.