Control válvula

Hola:

Hice un esquema con Proteus.

Ver captura.

Lo que tiene que hacer el programa y sigo con ello.

Entradas:
Tiene un interruptor llamado INTERRUPTOR.
Un pulsador normalmente cerrado llamado SPORT.

Salidas:
Tiene una salida que se llama VÁLVULA.

Explico de que va. En el interruptor principal lo puedes dejar en estado LOW o HIGH de forma fija.
Si lo dejas en HIGH el interruptor, tienes dos modos.

Modos:

  1. NORMAL.
  2. MODIFICADO.

Modo 1) en HIGH en el INTERRUPTOR, lo que hace es que la VÁLVULA siempre esté el circuito cerrado, o lo que es lo mismo, que siempre esté funcionando, ya que incluye un relé que siempre está en modo NC (Normalmente Cerrado) para que conmute.
En este modo 1) NORMAL, por mucho que pulses el botón SPORT, lo ignorará y la VÁLVULA siempre está activa o el relé en estado NC.

Modo 2) en LOW en el INTERRUPTOR, de entrada la VÁLVULA al encender Arduino siempre empiece cerrada, con el circuito en funcionamiento ya que el relé siempre estará normalmente cerrado. Ahora con el botón o pulsador SPORT, ya puedo abrir y cerrar la VÁLVULA cuando quiera.

Espero que hasta aquí se entienda bien lo básico de lo que quiero hacer.
Dejar claro que el pulsador o botón SPORT, es normalmente cerrado, que al pulsarlo y soltarlo vuelve a su posición. Por eso dentro de Arduino tiene que saber cuando se ha pulsado y cuando no.

Quiero saber mejor manera de programarlo. Por ahora he hecho lo básico y no se como hacerlo bien de todo.

// Constantes.
const byte pinInterruptor = 3;
const byte valvula =  4;
const byte sportBoton = 8;

// Variables.
byte estadoPinInterruptor = 0;
bool estadoSportBoton = 0;

void setup()
{
  // Configuración de los pines.
  pinMode(valvula, OUTPUT);
  pinMode(pinInterruptor, INPUT);
  pinMode(sportBoton, INPUT);
}

void loop()
{
  // Lee el estado del pulsador e interruptor.
  estadoPinInterruptor = digitalRead(pinInterruptor);
  estadoSportBoton = digitalRead(sportBoton);

  // Modo 1) Normal y 2) Modificado.
  if (estadoPinInterruptor == HIGH)
  {
    // Comprueba el estado del pulsador Sport ha sido pulsado.
    if (estadoSportBoton == HIGH)
    {
      digitalWrite(valvula, HIGH);
    }
    else
    {
      digitalWrite(valvula, LOW);
    }
  }
}

Hola @Metaconta
para hacer tu proyecto no necesitas un arduino. Simplemente use un CI Y como un CD4081.
Pero como estás usando arduino, hice algunas modificaciones para mejorar tu código.

RV mineirin

// Constantes.
const byte pinInterruptor = 3;
const byte valvula =  4;
const byte sportBoton = 8;

// Variables.
byte estadoPinInterruptor = 0;
bool estadoSportBoton = 0;
//--------------------------------------------
void setup()
{
  // Configuración de los pines.
  pinMode(valvula, OUTPUT);
  pinMode(pinInterruptor, INPUT);
  pinMode(sportBoton, INPUT);
  digitalWrite(valvula, LOW);
}
//--------------------------------------------
void loop()
{
  // Lee el estado del pulsador e interruptor.
  estadoPinInterruptor = digitalRead(pinInterruptor);
  estadoSportBoton = digitalRead(sportBoton);

  // Modo 1) Normal y 2) Modificado.
  if (estadoPinInterruptor == HIGH)
  {
    // Comprueba el estado del pulsador Sport ha sido pulsado.
    if (estadoSportBoton == HIGH)
    {
      digitalWrite(valvula, HIGH);
    }
    else
    {
      digitalWrite(valvula, LOW);
    }
  }
  else
  {
    digitalWrite(valvula, LOW);
  }
}

Buenas:

El código no funciona.

No olvidar que el pulsador o botón Sport, Normalmente es cerrado (NC). En el código falta alguna variable tipo bool. Lo comento porque si pulsas el botón Sport, vuelve a su posición, por eso debe haber una variable en el código booleano que se quede guardado.

Por ejemplo.

variable bool = false;

Botón Sport siempre está cerrado, lo pulso, y llega 0 a Arduino y vuelve el botón a su estado inicial y se pone a 1.

Ahora dentro de Arduino tiene que estar la variable así.
variable bool = true;

A partir de ahí ya se queda guardado en memoria RAM para que funcione dicho programa.

Por eso con el CD4081 no funcionaría porque no tiene memoria para guardar los estados.

Saludos.

EDITO:
Intenté hacerlo como muestra el código de abajo, pero no mantiene el estado.

// Constantes.
const byte pinInterruptor = 3;
const byte valvula =  4;
const byte sportBoton = 8;

// Variables.
byte estadoPinInterruptor = 0;
bool estadoSportBoton = false;
//--------------------------------------------
void setup()
{
  // Configuración de los pines.
  pinMode(valvula, OUTPUT);
  pinMode(pinInterruptor, INPUT);
  pinMode(sportBoton, INPUT);
  digitalWrite(valvula, LOW);
}
//--------------------------------------------
void loop()
{
  // Lee el estado del pulsador e interruptor.
  estadoPinInterruptor = digitalRead(pinInterruptor);
  estadoSportBoton = digitalRead(sportBoton);

  // Modo 1) Normal y 2) Modificado.
  if (estadoPinInterruptor == HIGH)
  {
    // Comprueba el estado del pulsador Sport ha sido pulsado.
    bool valor = digitalRead(estadoSportBoton); // Leemos el botón: false = LOW.
    if (valor == false) // Han pulsado el botón.
    {
      estadoSportBoton =! estadoSportBoton; // Cambiamos el estado.
      digitalWrite(valvula, estadoPinInterruptor); // Escribimos el nuevo valor.
    }
  }
  else
  {
    digitalWrite(valvula, LOW);
  }
}

La primer lectura de Sport está de más porque si depende del estado del Pulsador, la correcta es la que esté dentro del if().
El problema que tienes es que te olvidaste de trabajar con el flanco.
Compara el estado de Sport contra una variable que almacene el estado anterior del mismo.
Si cambió entonces guarda el estado y actúa si corresponde, sino no hace nada.
Otro detalle que no veo es algún filtro antirrebote tanto para Pulsador como para Sport. Y que no te quepan dudas que los tienen.

Saludos

Buenas:

Dejo claro que el pulsador SPORT tiene que estar siempre abierto, no cerrado como decía al principio del post.

No tengo tiempo para continuar. Esta vez se me olvidó poner el flag pero no el filtro antirebote. Dejo el código hecho por ahora aquí abajo y opinan. Recuerda, me falta poner el Flag.

// Constantes.
const byte pinInterruptor = 3;
const byte valvula =  4;
const byte sportBoton = 8;

// Variables.
byte estadoPinInterruptor = 0;
bool estadoSportBoton = false;

// Variable para pulsador antirebotes o bounce.
int estadoActual1 = 0;
int estadoActual2 = 0;
int estadoUltimo = 0;
int contador = 0;
//--------------------------------------------
void setup()
{
  // Configuración de los pines.
  pinMode(valvula, OUTPUT);
  pinMode(pinInterruptor, INPUT);
  pinMode(sportBoton, INPUT);
  digitalWrite(valvula, LOW);
  Serial.begin(9600);
}
//--------------------------------------------
void loop()
{
  // Lee el estado del pulsador e interruptor.
  estadoPinInterruptor = digitalRead(pinInterruptor);
  estadoSportBoton = digitalRead(sportBoton);

  // Modo 1) Normal y 2) Modificado.
  if (estadoPinInterruptor == HIGH)
  {
    // Comprueba el estado del pulsador Sport ha sido pulsado.
    estadoActual1 = sportBoton;
    delay(10);
    estadoActual2 = sportBoton;

    // ¿Los estados no son iguales?
    if (estadoActual1 == estadoActual2)
    {
      // ¿estadoACtual es distinto a estadoUltimo?
      if (estadoActual1 != estadoUltimo)
      {
        // ¿estadoActual es alto, 1, activado o HIGH?
        if (estadoActual1 == HIGH)
        {
          contador = contador + 1;
          Serial.print ("Ésta es la pulsación nº ");
          Serial.println(contador);
        }
      }
    }
    estadoUltimo = estadoActual1;

    if(contador % 2 == 0)
    {
      digitalWrite(valvula, LOW);
    }
    else
    {
      digitalWrite(valvula, HIGH);
    }
  }
  else
  {
    digitalWrite(valvula, LOW);
  }
  
}

Si notan algo raro que no sea solo el flag, avisen.

Saludos.

Hola:

Como puedes ver en el esquema, hay dos entradas y una salida.

Entradas:
INTERRUPTOR --> Es un interruptor normal.
SPORT --> Es un pulsador que si lo pulsas y lo dejas de pulsar, vuelve a su estado normal.

Salida:
Válvula

Si dejas el INTERRUPOR abierto que sería 0V, estaría en un modo que siempre la Válvula estaría cerrada. En este momento si pulsas el pulsador SPORT, lo ignora.
Si dejas el INTERRUPTOR cerrado que sería 5V, estaría en un modo en el cual ya te puede obedecer el pulsador SPORT.
Si pulsas una vez el pulsador SPORT, abre la Válvula, si lo vuelves a pulsar, cierra la Válvula.

Diagrama de flujo.

El código que he hecho hasta ahora no me funciona en Proteus 12 SP0.

Código Arduino:

C++:

// Constantes.
const byte pinInterruptor = 3;
const byte valvula =  4;
const byte sportBoton = 8;

// Variables.
byte estadoPinInterruptor = 0;
byte estadoSportBoton = 0;

// Variable para pulsador antirebotes o bounce.
int estadoActual1 = 0;
int estadoActual2 = 0;
int estadoUltimo = 0;
int contador = 0;
//--------------------------------------------
void setup()
{
  // Configuración de los pines.
  pinMode(valvula, OUTPUT);
  pinMode(pinInterruptor, INPUT);
  pinMode(sportBoton, INPUT);
  digitalWrite(valvula, LOW);
  Serial.begin(9600);
}
//--------------------------------------------
void loop()
{
  // Lee el estado del pulsador e interruptor.
  estadoPinInterruptor = digitalRead(pinInterruptor);
  estadoSportBoton = digitalRead(sportBoton);

  // Modo 1) Normal y 2) Modificado.

  // ¿INT pulsado?
  if (estadoPinInterruptor == HIGH)
  {
    // Sí. INT ha sido pulsado.
    // Comprueba el estado del pulsador Sport ha sido pulsado.
    estadoActual1 = sportBoton;
    delay(10);
    estadoActual2 = sportBoton;

    // ¿Los estados no son iguales?
    if (estadoActual1 == estadoActual2)
    {
      // ¿estadoACtual es distinto a estadoUltimo?
      if (estadoActual1 != estadoUltimo)
      {
        // ¿estadoActual es alto, 1, activado o HIGH?
        if (estadoActual1 == HIGH)
        {
          contador = contador + 1;
          Serial.print ("Ésta es la pulsación nº ");
          Serial.println(contador);
        }
      }
    }
    estadoUltimo = estadoActual1;

    if (contador % 2 == 0)
    {
      // Cerrar válvula.
      digitalWrite(valvula, LOW);
    }
    else
    {
      // Abrir válvula.
      digitalWrite(valvula, HIGH);
    }
  }
  else // Encontes. INT no ha sido pulsado.
  {
    // Cierra la válvula o el relé en NC.
    digitalWrite(valvula, LOW);
  }
}

Antes de comprar componentes y hacer una placa o PCB, quiero que en el simulador me funcione de maravilla.

¿Ves alguna solución?

Gracias

Ahora si! Te iba a avisar que no se veían las imágenes. :wink:

Al margen y es un detalle, el LED es de 12V? Porque así cono está conectado va a durar un suspiro.

Primero otros detalles del esquema.

Yo no pondría el transistor, directamente atacaría al opto con el pulsador.
Y por seguridad, porque sino ni pondría el opto; un divisor de tensión y un zener "por las dudas" y directo al pin.

Agrego: Otra opción interesante es un Mos-Fet como adaptador de nivel. Casi tan seguro como el opto y mucho mejor que un simple divisor.

Saludos

Hola @Metaconta
Sugerí construir su proyecto sin usar arduino usando m 4081, pero es un AND y el proyecto necesita un OR 4071.
Aquí están los archivos con el diseño del proyecto y el proyecto proteus para que los simules.
No sé cómo subir el archivo proteus aquí en el foro.

RV mineirin

Fijate si va

// Constantes.
const byte pinInterruptor = 3;
const byte valvula =  4;
const byte sportBoton = 8;

// Variables.
byte estadoPinInterruptor = 0;
byte estadoSportBoton = 0;

// Variable para pulsador antirebotes o bounce.
//int estadoActual1 = 0;
//int estadoActual2 = 0;
byte estadoUltimo;
byte contador = 0;
//--------------------------------------------
void setup()
{
  // Configuración de los pines.
  pinMode(valvula, OUTPUT);
  pinMode(pinInterruptor, INPUT);
  pinMode(sportBoton, INPUT);
  digitalWrite(valvula, LOW);
  Serial.begin(9600);
  estadoUltimo = digitalRead(sportBoton);
}
//--------------------------------------------
void loop()
{
  // Lee el estado del pulsador e interruptor.
  estadoPinInterruptor = digitalRead(pinInterruptor);
  delay(20); // antirrebote extremadamente basico
//  estadoSportBoton = digitalRead(sportBoton);

  // Modo 1) Normal y 2) Modificado.

  // ¿INT pulsado?
  if (estadoPinInterruptor == HIGH)
  {
    // Sí. INT ha sido pulsado.
    // Comprueba el estado del pulsador Sport ha sido pulsado.
    estadoSportBoton = digitalRead(sportBoton);
    delay(20); // antirrebote terriblemente basico

    // ¿Los estados no son iguales?
    if (estadoSportBoton != estadoUltimo)
    {
      estadoUltimo = estadoSportBoton;
        // ¿estadoActual es alto, 1, activado o HIGH?
      if (estadoSportBoton == HIGH)
      {
        contador = contador + 1;
        Serial.print ("Ésta es la pulsación nº ");
          Serial.println(contador);
      }
      if (contador == 0)
      {
      // Cerrar válvula.
        digitalWrite(valvula, LOW);
      }
      else
      {
        // Abrir válvula.
        digitalWrite(valvula, HIGH);
      }
      contador %= 2;
    }
  else // Encontes. INT no ha sido pulsado.
  {
    // Cierra la válvula o el relé en NC.
    digitalWrite(valvula, LOW);
  }
}

NOTA:
Hice una corrección 23:50 UTC :wink:

El 4071 puede trabajar directamente en 12V, yo simplificaría aún más el esquema. :wink:

Saludos

1 Like

Hola @gatul
Sí, es cierto, pero no quería cambiar esta parte del proyecto OP.

Saludos.
RV mineirin

Ok. Lo dije porque al eliminar el micro los 5V ya no serian necesarios (cambiando el relé, claro).

En sí era para redondear aún más tu idea.

Saludos

1 Like

El código de #11 no va.
Este es el bueno :wink:

// Constantes.
const byte pinInterruptor = 3;
const byte valvula =  4;
const byte sportBoton = 8;

// Variables.
byte estadoPinInterruptor = 0;
byte estadoSportBoton = 0;

byte estadoUltimo = 0;
bool abrirValvula = false;
//--------------------------------------------
void setup()
{
  // Configuración de los pines.
  pinMode(valvula, OUTPUT);
  pinMode(pinInterruptor, INPUT);
  pinMode(sportBoton, INPUT);
  digitalWrite(valvula, LOW);
  Serial.begin(9600);
  estadoUltimo = digitalRead(sportBoton);
}
//--------------------------------------------
void loop()
{
  // Lee el estado del pulsador e interruptor.
  estadoPinInterruptor = digitalRead(pinInterruptor);
  delay(20); // antirrebote ridículamente básico

  // Modo 1) Normal y 2) Modificado.

  // ¿INT pulsado?
  if (estadoPinInterruptor == HIGH){
    // Sí. INT ha sido pulsado.
    // Comprueba el estado del pulsador Sport ha sido pulsado.
    estadoSportBoton = digitalRead(sportBoton);
    delay(20); // antirrebote extremadamente básico

    // ¿Los estados no son iguales?
    if (estadoSportBoton != estadoUltimo)
    {
      estadoUltimo = estadoSportBoton;
        // ¿estadoActual es alto, 1, activado o HIGH?
      if (estadoSportBoton == HIGH)
      {
        abrirValvula = !abrirValvula;
        if (abrirValvula){
        // Abrir válvula.
          digitalWrite(valvula, HIGH);
        }
        else {
      // Cerrar válvula.
          digitalWrite(valvula, LOW);
        }
      }
    }
  }
  else {// Encontes. INT no ha sido pulsado.
    // Cierra la válvula o el relé en NC.
    digitalWrite(valvula, LOW);
    abrirValvula = false;  // por si se abre interruptor mientras la válvula estaba abierta
  }
}

Hola:

Muy bueno el comentario.
Ya lo había hecho hace horas. Me acabo de levantar y en este momentos en pocos minutos me voy a trabajar. Antes, dejo el código que si funciona, no significa que sea el mejor.

// Constantes.
const byte pinInterruptor = 3;
const byte valvula =  4;
const byte sportBoton = 8;

// Variables.
byte estadoPinInterruptor = 0;
byte estadoSportBoton = 0;

// Variable para pulsador antirebotes o bounce.
int estadoActual1 = 0;
int estadoActual2 = 0;
int estadoUltimo = 0;
int contador = 0;
//--------------------------------------------
void setup()
{
  // Configuración de los pines.
  pinMode(valvula, OUTPUT);
  pinMode(pinInterruptor, INPUT);
  pinMode(sportBoton, INPUT);
  digitalWrite(valvula, LOW);
  Serial.begin(9600);
}
//--------------------------------------------
void loop()
{
  // Lee el estado del pulsador e interruptor.
  estadoPinInterruptor = digitalRead(pinInterruptor);
  estadoSportBoton = digitalRead(sportBoton);

  // Modo 1) Normal y 2) Modificado.

  // ¿INT pulsado?
  if (estadoPinInterruptor == HIGH)
  {
    // Sí. INT ha sido pulsado.
    // Comprueba el estado del pulsador Sport ha sido pulsado.
    estadoActual1 = estadoSportBoton;
    delay(10);
    estadoActual2 = estadoSportBoton;

    // ¿Los estados no son iguales?
    if (estadoActual1 == estadoActual2)
    {
      // ¿estadoACtual es distinto a estadoUltimo?
      if (estadoActual1 != estadoUltimo)
      {
        // ¿estadoActual es alto, 1, activado o HIGH?
        if (estadoActual1 == HIGH)
        {
          contador = contador + 1;
          Serial.print ("Ésta es la pulsación nº ");
          Serial.println(contador);
        }
      }
    }
    estadoUltimo = estadoActual1;

    if (contador % 2 == 0)
    {
      // Cerrar válvula.
      digitalWrite(valvula, LOW);
    }
    else
    {
      // Abrir válvula.
      digitalWrite(valvula, HIGH);
    }
  }
  else // Encontes. INT no ha sido pulsado.
  {
    // Cierra la válvula o el relé en NC.
    digitalWrite(valvula, LOW);
  }
}

El tema del 4071 de este esquema presentado por el amigo.

Hay un dilema. No incluye Flag como si lo hace Arduino. Por eso no funciona como debería, este mismo lo voy a probar empezarlo desde cero, gracias por el diseño.

Cuando llegue a mi casa lo pruebo, si es posible, si no se usa Arduino que es muy grande, prefiero un OR, pero quiero saber si funciona exactamente como en Arduino, me ahorraría muchos componentes y tamaño.

Por cierto, sobre el tema de los antirrebotes hecho por hardware como se hacía antes, hay que incluirlos. Este modelo puede funcionar.

Más información.

Muchas gracias a todos y atento en leerles.

Al circuito de @ruilviana le faltaría un flip-flop para que trabaje como quieres.

Saludos

Holaaaaaaaa:

Habría que probarlo. También faltaría en toda regla en las entradas digitales como pulsadores e interruptores disparador de Schmitt o inversor con histéresis.

Naaah. No exageres que no es para tanto en este caso. :grimacing:

Te digo más, la puerta OR tranquilamente la reemplazas con 2 diodos, el tema es el flip-flop, pero con un par de transistores se soluciona.

No niego que el micro (con un Tiny, sobra) simplifica la tarea pero si se quiere hacer discreto también se puede.

Saludos

Buenas:

¿Qué diodos le vas a sustituir exactamente a esto?

Dije la puerta OR no el flip-flop.
La puerta OR se puede hacer "cableada"