Quiero que el switch case no se repita-Contador de pulsos

Hola
Soy nuevo en el foro y apenas estoy empezando en la programación de arduino, espero y puedan ayudarme.
Antes que nada ya estuve buscando en Internet como poder solucionar mi problema pero no he encontrado algo que pueda ayudarme hasta ahora.

Estoy haciendo un circuito que utiliza un sensor de movimiento como entrada digital de arduino, es un PIR, quiero que cada vez que el sensor mande un HIGH (detecto movimiento) me encienda un foco y a la vez me muestre un conteo binario del 0 al 15 en unos LEDs.
Para el encendido y apagado del foco use la instruccion if y para el contador el switch case, y funciona, el problema es que el tiempo que el sensor PIR manda un 1 (HIGH) dura lo suficiente como para que el contador incremente cuatro veces.
Siendo que cada vez que detecta movimiento se cuentan de 4 en 4. Yo quiero saber si es posible que el switch case detecte el HIGH del sensor, me haga el incremento, pero que cuando regrese a void loop (para entonces el sensor sigue en HIGH) no vuelva a incrementar sino que espera a que se ponga en LOW y de nuevo en HIGH para hacer otro incremento.
Si hay otra forma de hacer el conteo si usar case les agradecería mucho su ayuda.

float cuenta;

 int numero = 0; 

 int estado;              //Variable que cambiara de acuerdo al estado del sensor.
void setup() {
  pinMode (pinSensor, INPUT);  //El pin del sensor se configura como entrada.
  pinMode (pinFoco, OUTPUT);   //El pin del foco se configura como salida.
  pinMode (b4, OUTPUT);
  pinMode (b3, OUTPUT);
  pinMode (b2, OUTPUT);
  pinMode (b1, OUTPUT);
  digitalWrite (pinFoco, LOW); //El pin del foco se pone en bajo como estado inicial.
  }
  
 void retardo(){
for (cuenta=0; cuenta < 50000; cuenta++) {
 }
} 

void binario(int v4, int v3, int v2, int v1){ 
digitalWrite(b4,v4);
digitalWrite(b3,v3);
digitalWrite(b2,v2);
digitalWrite(b1,v1);
}

  void loop() {
    estado = digitalRead (pinSensor); //Lee el estado del sensor.
    if (estado == HIGH) {             //Si el sensor detecta movimiento:
      digitalWrite (pinFoco, HIGH);   //Poner el pin del foco en alto, activando el rele, encendiendo el foco.
      } 
      else {                          //Si el sensor no detecta movimiento:
      digitalWrite (pinFoco, LOW);    //Pone el pin del foco en bajo, desactivando el rele, apagando el foco.
        }
        if (estado == HIGH and numero <16) { 
    numero = numero + 1; 
  }
  if (numero == 16){
    numero = numero - 16;
  }
  switch (numero) { 
    case 0:       
      binario(0,0,0,0);   
      break; 
    case 1:       
      binario(0,0,0,1); 
      break; 
    case 2:       
      binario(0,0,1,0); 
      break; 
    case 3:       
      binario(0,0,1,1); 
      break; 
    case 4:      
      binario(0,1,0,0); 
      break; 
    case 5:       
      binario(0,1,0,1);  
      break; 
    case 6:      
      binario(0,1,1,0); 
      break; 
    case 7:       
      binario(0,1,1,1);  
      break; 
    case 8:       
      binario(1,0,0,0);
      break; 
    case 9:       
      binario(1,0,0,1);  
      break;
    case 10:       
      binario(1,0,1,0); 
      break; 
    case 11:       
      binario(1,0,1,1); 
      break; 
    case 12:       
      binario(1,1,0,0); 
      break; 
    case 13:       
      binario(1,1,0,1); 
      break; 
    case 14:       
      binario(1,1,1,0); 
      break; 
    case 15:       
      binario(1,1,1,1); 
      break;    
  } 
retardo();
}

Prueba este código modificado del tuyo.
Solucioné tu problema de rebote.
Simplifiqué tu función de número a bcd.

byte numero = 0; 
bool estado = false;              //Variable que cambiara de acuerdo al estado del sensor.
bool estadoAnt = false;

void setup() {
  pinMode (pinSensor, INPUT);  //El pin del sensor se configura como entrada.
  pinMode (pinFoco, OUTPUT);   //El pin del foco se configura como salida.
  pinMode (b4, OUTPUT);
  pinMode (b3, OUTPUT);
  pinMode (b2, OUTPUT);
  pinMode (b1, OUTPUT);
  digitalWrite (pinFoco, LOW); //El pin del foco se pone en bajo como estado inicial.
}
  
void binario(int numero) {
    byte v1 =  numero && 0x01;
    byte v2 = (numero && 0x02)>>1;
    byte v3 = (numero && 0x04)>>2;
    byte v4 = (numero && 0x08)>>3;

	digitalWrite(b4, v4);
	digitalWrite(b3, v3);
	digitalWrite(b2, v2);
	digitalWrite(b1, v1);
}

 void loop() {
    estado = digitalRead (pinSensor); //Lee el estado del sensor.
    if (estado == HIGH && estadoAnt == LOW) {             //Si el sensor detecta movimiento:
      digitalWrite (pinFoco, HIGH);   //Poner el pin del foco en alto, activando el rele, encendiendo el foco.
      if (numero++ >= 16)
         numero = 0;	
    } 
    else {                            //Si el sensor no detecta movimiento:
      digitalWrite (pinFoco, LOW);    //Pone el pin del foco en bajo, desactivando el rele, apagando el foco.
    }
    
    estadoAnt = estado;

    binario(numero);
    delay(1000),
}

Pero tu programa hacia lo mismo.
Con solo que con los rebotes incrementaba y ahora no tienes rebotes.

Veamos asi

byte numero = 0; 
bool estado = false;              //Variable que cambiara de acuerdo al estado del sensor.
bool estadoAnt = false;
bool contadorOn = false;

void setup() {
  pinMode (pinSensor, INPUT);  //El pin del sensor se configura como entrada.
  pinMode (pinFoco, OUTPUT);   //El pin del foco se configura como salida.
  pinMode (b4, OUTPUT);
  pinMode (b3, OUTPUT);
  pinMode (b2, OUTPUT);
  pinMode (b1, OUTPUT);
  digitalWrite (pinFoco, LOW); //El pin del foco se pone en bajo como estado inicial.
}
  
void binario(int numero) {
    byte v1 =  numero && 0x01;
    byte v2 = (numero && 0x02)>>1;
    byte v3 = (numero && 0x04)>>2;
    byte v4 = (numero && 0x08)>>3;

	digitalWrite(b4, v4);
	digitalWrite(b3, v3);
	digitalWrite(b2, v2);
	digitalWrite(b1, v1);
}

 void loop() {
    estado = digitalRead (pinSensor); 				//Lee el estado del sensor.

    if (estado == HIGH && estadoAnt == LOW) {       //Si el sensor detecta movimiento:
      digitalWrite (pinFoco, HIGH);   				//Poner el pin del foco en alto, activando el rele, encendiendo el foco.
      contadorOn = true;	
    }

    if { estado == LOW && estadoAnt == HIGH) {    	//Si el sensor no detecta movimiento:
      digitalWrite (pinFoco, LOW);    				//Pone el pin del foco en bajo, desactivando el rele, apagando el foco.
      contadorON = false;
    }
    estadoAnt = estado;
	
	if (numero++ >= 16 && contadorON)
         numero = 0;
    binario(numero);
    delay(1000),
}}

Buenas, como primera medida, disculpen mi ignorancia, por ahi me estoy metiendo en cosas que por mi corta experiencia no debo, pero como no tenia ni idea de que era un contador binario me pico la curiosidad, asi que lei un poco y realize la prueba de EduardoOlvCast, y efectivamente me hace lo que el dice avanza segun duracion del sensor, simule la primera de surbyte y solo me enciende 0001 hasta la vez 16 que hace 0000 y repite.
No se si habre hecho algo mal.
Teniendo en cuenta que si estas permanentemente delante del sensor, es como una sola captacion yo le puse un delay (1000) para poner el foco LOW y luego un delay (3000) para que el ciclo pueda iniciarse nuevamente y no me rebota, cuenta con una cadencia logica.

float cuenta;

 int numero = 0; 
 int estado;              //Variable que cambiara de acuerdo al estado del sensor.
 int pinSensor = 3;
int pinFoco = 4;
int b4 = 5;
int b3 = 6;
int b2 = 7;
int b1 = 8;
 
void setup() {
  pinMode (pinSensor, INPUT);  //El pin del sensor se configura como entrada.
  pinMode (pinFoco, OUTPUT);   //El pin del foco se configura como salida.
  pinMode (b4, OUTPUT);
  pinMode (b3, OUTPUT);
  pinMode (b2, OUTPUT);
  pinMode (b1, OUTPUT);
  digitalWrite (pinFoco, LOW); //El pin del foco se pone en bajo como estado inicial.
  }
  
 void retardo(){
for (cuenta=0; cuenta < 50000; cuenta++) {
 }
} 

void binario(int v4, int v3, int v2, int v1){ 
digitalWrite(b4,v4);
digitalWrite(b3,v3);
digitalWrite(b2,v2);
digitalWrite(b1,v1);
}

  void loop() {
    estado = digitalRead (pinSensor); //Lee el estado del sensor.
    if (estado == HIGH) {             //Si el sensor detecta movimiento:
      digitalWrite (pinFoco, HIGH);   //Poner el pin del foco en alto, activando el rele, encendiendo el foco.
    delay (1000);
  digitalWrite (pinFoco, LOW);
delay (3000);  
    } 
      else {                          //Si el sensor no detecta movimiento:
      digitalWrite (pinFoco, LOW);    //Pone el pin del foco en bajo, desactivando el rele, apagando el foco.
        }
        if (estado == HIGH and numero <16) { 
    numero = numero + 1; 
  }
  if (numero == 16){
    numero = numero - 16;
  }
  switch (numero) { 
    case 0:       
      binario(0,0,0,0);   
      break; 
    case 1:       
      binario(0,0,0,1); 
      break; 
    case 2:       
      binario(0,0,1,0); 
      break; 
    case 3:       
      binario(0,0,1,1); 
      break; 
    case 4:      
      binario(0,1,0,0); 
      break; 
    case 5:       
      binario(0,1,0,1);  
      break; 
    case 6:      
      binario(0,1,1,0); 
      break; 
    case 7:       
      binario(0,1,1,1);  
      break; 
    case 8:       
      binario(1,0,0,0);
      break; 
    case 9:       
      binario(1,0,0,1);  
      break;
    case 10:       
      binario(1,0,1,0); 
      break; 
    case 11:       
      binario(1,0,1,1); 
      break; 
    case 12:       
      binario(1,1,0,0); 
      break; 
    case 13:       
      binario(1,1,0,1); 
      break; 
    case 14:       
      binario(1,1,1,0); 
      break; 
    case 15:       
      binario(1,1,1,1); 
      break;    
  } 
retardo();
}

He puesto un pequeño video del uso, no se si lo habre subido bien, ya que no tenia ni idea de subir algo a Dropbox.
Por favor comentenme algo para segir aprendiendo.
Saludos

mira el nuevo código.

Muchas gracias por intentar ayudarme, surbyte tu código no me funciono y no le entendí muy bien la verdad y cuervo tu código logro que incrementara hasta 3 pero luego se reiniciaba.
Perdón porque a pesar de sus intentos por ayudarme no logre completarlo. Después lo veré a detalle por que ahora estoy muy apretado en tareas y si lo soluciono gracias a sus consejos se los haré saber.

Bueno tienes las sugerencias, ponle un poco de tu tiempo y saldrá adelante.

Hola muy buenas, yo tengo el mismo problema, pero al revés,
he hecho un pequeño programa en visual basic 6 ( :o ya lo sé..., muy viejo...) para que se comunique con mi Arduino Uno rev3, en ese apartado no tengo problemas, pues mi programita envia y recibe (no despues de pocos esfuerzos!) perferctamente,
el problema lo tengo el el sketch de Arduino,
yo he programado antes en C++, y como la programacion de Arduino es básicamente C, pensé en adaptar un .hex de mis viejos PICs, el sketch está pero tengo un problema con el switch-case,
necesito que el switch-case se repita hasta que una variable cambie de valor, he escrito y re-escrito el codigo como 10 veces, y solo consigo que cada case lo repita una sola vez, o que se "atranque" en uno de ellos. No se si es por que ya no sé ni lo que miro, o porque he olvidado programar C, o que en Arduino hay otra forma de hacerlo... añado el codigo del sketch por si alguien me puede ayudar... Gracias!!! :slight_smile:
Por cierto, el programa es para mover dos motores a pasos! olvide comentarlo!

#include <Stepper.h>

const int stepsPerRevolution = 200;
Stepper myStepper(stepsPerRevolution, 8, 9, 10, 11);
int stepCount = 0;
const int sw1 = A1;
const int sw2 = A2;
int dirSw1State = 0;
int dirSw2State = 0;

void setup() {                                     //Función "setup"
  pinMode(13, OUTPUT);                             //Definimos el pin 13 como salida
  Serial.begin(9600);                              //y la velocidad de transferencia a 9600 baudios
}                                                  //Final de la función "setup"

void loop() {                                      //Funcion "loop"
  dirSw1State = digitalRead(sw1);                  //
  dirSw2State = digitalRead(sw2);                  //
  byte xdato = 0;                                  //Variable "xdato" = "0" (para detectar cambios durante la ejecucion del "do-while")
  
  while (Serial.available())                       //Mientras el puerto serie este accesible
  {                                                //
    delay(50);                                     //Espera para recibir datos              
    byte dato = Serial.read();                     //Asigana a "dato" el valor recibido
    switch (dato) {                                //En base al valor de "dato"
                                                   /////////////////////////////////////////////////////
      case '1':                                    //Si "dato = '1'
        do {                                       //Este bucle se ejecuta al menos una vez
          if(Serial.available() > 0){              //Si se reciben datos por el puerto serie
            delay(50);                             //Espera para recibir datos
            dato = Serial.read();                  //Asigana a "dato" el valor recibido
            if(dato == '1'){                       //Si "dato = '1'
              xdato = '1';                         //La variable "xdato" = '1'
            }                                      //
            else if(dato != '1'){                  //Si "dato" es distinto de '1'
              xdato = '0';                         //La variable "xdato" = '0'
            }                                      //
          }                                        //
          int sensorReading = analogRead(A0);                      //read the sensor value
          int motorSpeed = map(sensorReading, 0, 1023, 0, 100);    //map it to a range from 0 to 100
          if (motorSpeed > 0) {                                    //Si la variable "motorSpeed" es mayor de "0"                                    
            myStepper.setSpeed(motorSpeed);                        //set the motor speed
            myStepper.step(stepsPerRevolution / 100);              //step 1/100 of a revolution
          }                                                        //
        }while (xdato == '1');                    //Final del bucle "do-while" (se ejecuta mientras la variable "xdato" = 1
        digitalWrite(13, HIGH);                   //Encendemos el led
        Serial.write("Derecha");                  //Enviamos la cadena "Derecha" por el puerto serie
        continue;                                 //Salida de "case '1'"
                                                  /////////////////////////////////////////////////////
      case '2':                                   //Si "dato = '2'
        do {                                      //Este bucle se ejecuta al menos una vez
          if(Serial.available() > 0){             //Si se reciben datos por el puerto serie
            delay(50);                            //Espera para recibir datos
            dato = Serial.read();                 //Asigana a "dato" el valor recibido
            if(dato == '2'){                      //Si "dato = '2'
              xdato = '2';                        //La variable "xdato" = '2'
            }                                     //
            else if(dato != '2'){                 //Si "dato" es distinto de '2'
              xdato = '0';                        //La variable "xdato" = '0'
            }                                     //
          }                                       //
          int sensorReading = analogRead(A0);                        //read the sensor value:
          int motorSpeed = map(sensorReading, 0, 1023, 0, 100);      //map it to a range from 0 to 100:
          if (motorSpeed > 0) {                                      //Si la variable "motorSpeed" es mayor de "0"
            myStepper.setSpeed(motorSpeed);                          //set the motor speed
            myStepper.step((stepsPerRevolution / 100) * -1);         //step 1/100 of a revolution:
          }                                                          //
        }while (xdato == '2');                    //Final del bucle "do-while" (se ejecuta mientras la variable "xdato" = 1
        digitalWrite(13, LOW);                    //Apagamos el led
        Serial.write("Izquierda");                //Enviamos el string "Izquierda" por el puerto serie
        continue;                                 //Salida de "case '2'"
    }                                             //Final del Bucle "switch"
  }                                               //Final del bucle "while"
}                                                 //Final de la funcion "loop"

PD: no se si es correcto comentar esto en este hilo, o es más correcto crear un hilo nuevo, de estar en el sitio equivocado siento la molestia y agradecia que me comentaseis, gracias por todo!!

_Gromek:
Hola muy buenas, yo tengo el mismo problema, pero al revés,
he hecho un pequeño programa en visual basic 6 ( :o ya lo sé..., muy viejo...) para que se comunique con mi Arduino Uno rev3, en ese apartado no tengo problemas, pues mi programita envia y recibe (no despues de pocos esfuerzos!) perferctamente,
el problema lo tengo el el sketch de Arduino,
yo he programado antes en C++, y como la programacion de Arduino es básicamente C, pensé en adaptar un .hex de mis viejos PICs, el sketch está pero tengo un problema con el switch-case,
necesito que el switch-case se repita hasta que una variable cambie de valor, he escrito y re-escrito el codigo como 10 veces, y solo consigo que cada case lo repita una sola vez, o que se "atranque" en uno de ellos. No se si es por que ya no sé ni lo que miro, o porque he olvidado programar C, o que en Arduino hay otra forma de hacerlo... añado el codigo del sketch por si alguien me puede ayudar... Gracias!!! :slight_smile:
Por cierto, el programa es para mover dos motores a pasos! olvide comentarlo!

#include <Stepper.h>

const int stepsPerRevolution = 200;
Stepper myStepper(stepsPerRevolution, 8, 9, 10, 11);
int stepCount = 0;
const int sw1 = A1;
const int sw2 = A2;
int dirSw1State = 0;
int dirSw2State = 0;

void setup() {                                    //Función "setup"
  pinMode(13, OUTPUT);                            //Definimos el pin 13 como salida
  Serial.begin(9600);                              //y la velocidad de transferencia a 9600 baudios
}                                                  //Final de la función "setup"

void loop() {                                      //Funcion "loop"
  dirSw1State = digitalRead(sw1);                  //
  dirSw2State = digitalRead(sw2);                  //
  byte xdato = 0;                                  //Variable "xdato" = "0" (para detectar cambios durante la ejecucion del "do-while")
 
  while (Serial.available())                      //Mientras el puerto serie este accesible
  {                                                //
    delay(50);                                    //Espera para recibir datos             
    byte dato = Serial.read();                    //Asigana a "dato" el valor recibido
    switch (dato) {                                //En base al valor de "dato"
                                                  /////////////////////////////////////////////////////
      case '1':                                    //Si "dato = '1'
        do {                                      //Este bucle se ejecuta al menos una vez
          if(Serial.available() > 0){              //Si se reciben datos por el puerto serie
            delay(50);                            //Espera para recibir datos
            dato = Serial.read();                  //Asigana a "dato" el valor recibido
            if(dato == '1'){                      //Si "dato = '1'
              xdato = '1';                        //La variable "xdato" = '1'
            }                                      //
            else if(dato != '1'){                  //Si "dato" es distinto de '1'
              xdato = '0';                        //La variable "xdato" = '0'
            }                                      //
          }                                        //
          int sensorReading = analogRead(A0);                      //read the sensor value
          int motorSpeed = map(sensorReading, 0, 1023, 0, 100);    //map it to a range from 0 to 100
          if (motorSpeed > 0) {                                    //Si la variable "motorSpeed" es mayor de "0"                                   
            myStepper.setSpeed(motorSpeed);                        //set the motor speed
            myStepper.step(stepsPerRevolution / 100);              //step 1/100 of a revolution
          }                                                        //
        }while (xdato == '1');                    //Final del bucle "do-while" (se ejecuta mientras la variable "xdato" = 1
        digitalWrite(13, HIGH);                  //Encendemos el led
        Serial.write("Derecha");                  //Enviamos la cadena "Derecha" por el puerto serie
        continue;                                //Salida de "case '1'"
                                                  /////////////////////////////////////////////////////
      case '2':                                  //Si "dato = '2'
        do {                                      //Este bucle se ejecuta al menos una vez
          if(Serial.available() > 0){            //Si se reciben datos por el puerto serie
            delay(50);                            //Espera para recibir datos
            dato = Serial.read();                //Asigana a "dato" el valor recibido
            if(dato == '2'){                      //Si "dato = '2'
              xdato = '2';                        //La variable "xdato" = '2'
            }                                    //
            else if(dato != '2'){                //Si "dato" es distinto de '2'
              xdato = '0';                        //La variable "xdato" = '0'
            }                                    //
          }                                      //
          int sensorReading = analogRead(A0);                        //read the sensor value:
          int motorSpeed = map(sensorReading, 0, 1023, 0, 100);      //map it to a range from 0 to 100:
          if (motorSpeed > 0) {                                      //Si la variable "motorSpeed" es mayor de "0"
            myStepper.setSpeed(motorSpeed);                          //set the motor speed
            myStepper.step((stepsPerRevolution / 100) * -1);        //step 1/100 of a revolution:
          }                                                          //
        }while (xdato == '2');                    //Final del bucle "do-while" (se ejecuta mientras la variable "xdato" = 1
        digitalWrite(13, LOW);                    //Apagamos el led
        Serial.write("Izquierda");                //Enviamos el string "Izquierda" por el puerto serie
        continue;                                //Salida de "case '2'"
    }                                            //Final del Bucle "switch"
  }                                              //Final del bucle "while"
}                                                //Final de la funcion "loop"




PD: no se si es correcto comentar esto en este hilo, o es más correcto crear un hilo nuevo, de estar en el sitio equivocado siento la molestia y agradecia que me comentaseis, gracias por todo!!

Yo creo que lo mejor seria postearlo en el foro principal, ya que soy nuevo en esto de la programacion con C asi que no podria ayudarte. Espero puedas encontrar la solucion a tu problema.

Asi lo haré, gracias