Go Down

Topic: Arduino + Electrovalvula (conectada por relay 220v) + RTC + Caudalimetro (Read 209 times) previous topic - next topic

santilococo

Hola, alguno sabe como podría hacer que cuando se apriete un interruptor y pase un día se active la electrovalvula (el relay especificamente)? La idea de mi proyecto es hacer que por día se usen una cierta cantidad de litros (por ejemplo 5L) y cuando esta se sobrepasa se corta el relay y no saldra más agua hasta el otro día. Tiene que ser flexible porque yo tengo que poder usar esos 5L cuando quiera durante el día pero una vez que se terminan tengo que esperar al dia siguiente (sabes como se programaría eso? yo lo hice con un evento de alarma pero no creo que sea lo mas conveniente porque si  se llega a desconectar el arduino la alarma ya no funciona, es decir tiene que esperarse un dia mas y yo no quiero esto). Y entonces las tres variables que se tendrian que cumplir para que se encienda la electrovalvula es si hay cantidad de litros para usar, si paso un dia y si se toco el interruptor (como hago lo del interruptor?).

Paso el codigo a continuación:
Code: [Select]

//Librerias
#include <Time.h>
#include <TimeAlarms.h>
#include <DS1307RTC.h>
#include <Wire.h>
#include <EEPROM.h>

//Definimos variables
int electro_in1 = 12;
int electro_in2 = 11;

byte sensorInterrupt = 0;  // 0 = digital pin 2
byte sensorPin       = 2;
float calibrationFactor = 7.5;
volatile byte pulseCount; 
float flowRate;
float totalLitres;
unsigned long oldTime;

float volumen = 0;
float volumenMaximo = 5; //CAMBIAR ESTO DEPENDIENDO LOS LITROS MÁXIMOS

void pulseCounter()
{
  // Increment the pulse counter
  pulseCount++;
}



void setup()
{
   // Initialize a serial connection for reporting values to the host
  Serial.begin(9600);
   
  // Set up the status LED line as an output
  pinMode(electro_in1, OUTPUT);
  pinMode(electro_in2, OUTPUT);
  digitalWrite(electro_in1, HIGH);
  digitalWrite(electro_in2, HIGH);
 
  pinMode(sensorPin, INPUT);
  digitalWrite(sensorPin, HIGH);

  pulseCount        = 0;
  flowRate          = 0.0;
  totalLitres       = 0.0;
  oldTime           = 0;
 
  // The Hall-effect sensor is connected to pin 2 which uses interrupt 0.
  // Configured to trigger on a FALLING state change (transition from HIGH
  // state to LOW state)
  attachInterrupt(sensorInterrupt, pulseCounter, FALLING);

  //Para el RTC
  setSyncProvider(RTC.get);
  Alarm.alarmRepeat(00, 28, 10, ReiniciarVolumen);  // Evento diario, podriamos ponerla a las 00,00,01. ESTO ME GUSTARIA CAMBIAR
 
}



void loop()
{
   Alarm.delay(1000);

   if (volumen < volumenMaximo)
   if((millis() - oldTime) > 1000)    // Only process counters once per second
  {
    detachInterrupt(sensorInterrupt);
    flowRate = ((1000.0 / (millis() - oldTime)) * pulseCount) / calibrationFactor;
    oldTime = millis();
   
    // Add the millilitres passed in this second to the cumulative total
    totalLitres += flowRate / 60;
    volumen = totalLitres;
     
    unsigned int frac;
           
   
    Serial.print ("Caudal: ");
    Serial.print (flowRate,3);
    Serial.print ("L/min\tVolumen: ");
    Serial.print (volumen,3);
    Serial.println (" L");
     
    // Reset the pulse counter so we can start incrementing again
    pulseCount = 0;
   
    // Enable the interrupt again now that we've finished sending output
    attachInterrupt(sensorInterrupt, pulseCounter, FALLING); 
}

 if (volumen >= volumenMaximo){
      digitalWrite(electro_in1, HIGH);
      digitalWrite(electro_in2, HIGH);
    }

}



void ReiniciarVolumen() // de las alarmas!!!
{
 
  //Aca podria ir lo del boton para iniciar la electrovalvula
 
  if ( /* boton apretado && */ volumen < volumenMaximo){
  digitalWrite(electro_in1, LOW);
  digitalWrite(electro_in2, LOW);
  }
  else {
  digitalWrite(electro_in1, HIGH);
  digitalWrite(electro_in2, HIGH);
}
}


DETALLES:
-Tengo Arduino UNO
-Componentes ultilizados: (Relay 5V, Electrovalvula de 220v, Reloj DS1307, Caudalimetro YF-S201)

Desde ya muchisimas gracias!! Si no me explique bien diganme que no entendieron! Cualquier ayuda me es muy útil!
"Hay una fuerza motriz más poderosa que el vapor, la electricidad y la energía atómica: la voluntad." Albert Einstein

surbyte

Primer cambio
Code: [Select]
volatile unsigned int pulseCount; 

tener una variable como byte solo te permite 0 a 255 de tu contador lo que para un caudalimetro es poco.
La pasé a unsigned int lo que te da 0 a 65525.

He agregado un pulsador al pin 3 y lo debes conectar directamente entre GND y pin 3

Veamos como se comportan las 3 situaciones.
Code: [Select]

//Librerias
#include <Time.h>
#include <TimeAlarms.h>
#include <DS1307RTC.h>
#include <Wire.h>
#include <EEPROM.h>

//Definimos variables
int electro_in1         = 12;
int electro_in2         = 11;

byte sensorInterrupt    = 0;  // 0 = digital pin 2
const byte sensorPin    = 2;
const byte pulsadorPin  = 3;    // conectar aqui el pulsador entre pin y GND
float calibrationFactor = 7.5;
volatile unsigned int pulseCount; 
float flowRate;
float totalLitres;
unsigned long oldTime;
bool estado, estadoAnt = false;

float volumen = 0;
float volumenMaximo = 5; //CAMBIAR ESTO DEPENDIENDO LOS LITROS MÁXIMOS

void pulseCounter()
{
  // Increment the pulse counter
  pulseCount++;
}



void setup()
{
   // Initialize a serial connection for reporting values to the host
  Serial.begin(9600);
   
  // Set up the status LED line as an output
  pinMode(electro_in1, OUTPUT);
  pinMode(electro_in2, OUTPUT);
  digitalWrite(electro_in1, HIGH);
  digitalWrite(electro_in2, HIGH);
 
  pinMode(sensorPin, INPUT);
  pinMode(pulsadorPin, INPUT_PULLUP);  // pulsador entre pin 3 y GND.
  digitalWrite(sensorPin, HIGH);

  pulseCount        = 0;
  flowRate          = 0.0;
  totalLitres       = 0.0;
  oldTime           = 0;
 
  // The Hall-effect sensor is connected to pin 2 which uses interrupt 0.
  // Configured to trigger on a FALLING state change (transition from HIGH
  // state to LOW state)
  attachInterrupt(sensorInterrupt, pulseCounter, FALLING);

  //Para el RTC
  setSyncProvider(RTC.get);
  Alarm.alarmRepeat(00, 28, 10, ReiniciarVolumen);  // Evento diario, podriamos ponerla a las 00,00,01. ESTO ME GUSTARIA CAMBIAR
 
}

void loop() {

    estado = digitalRead(pulsador);

    if (estado && estadoAnt) {
        flag = true;

    }
    estadoAnt = estado;

    if (volumen < volumenMaximo)
        if ((millis() - oldTime) > 1000)  {  // Only process counters once per second
            detachInterrupt(sensorInterrupt);
            flowRate = ((1000.0 / (millis() - oldTime)) * pulseCount) / calibrationFactor;
           
           
            // Add the millilitres passed in this second to the cumulative total
            totalLitres += flowRate / 60;
            volumen = totalLitres;
             
            // unsigned int frac;
            Serial.print ("Caudal: ");
            Serial.print (flowRate,3);
            Serial.print ("L/min\tVolumen: ");
            Serial.print (volumen,3);
            Serial.println (" L");

            if (volumen > volumenMaximo ){/* boton apretado && */
                flag = true;
            }
             
            // Reset the pulse counter so we can start incrementing again
            pulseCount = 0;
           
            // Enable the interrupt again now that we've finished sending output
            attachInterrupt(sensorInterrupt, pulseCounter, FALLING); 
            oldTime = millis();
        }

    if (flag)
        ControlValvula();

    Alarm.delay(1000);
}


// de las alarmas!!!
void ReiniciarVolumen() {
  flag = true;
}

void ControlValvula() {
  //Aca podria ir lo del boton para iniciar la electrovalvula
  if (flag) {
      digitalWrite(electro_in1, HIGH);
      digitalWrite(electro_in2, HIGH);
      flag = false;
  }
  else {
      digitalWrite(electro_in1, LOW);
      digitalWrite(electro_in2, LOW);
  }
}

santilococo

Muchísimas gracias! Mañana lo pruebo y te digo, SOS UN GENIO!!!
Saludos!!!!
"Hay una fuerza motriz más poderosa que el vapor, la electricidad y la energía atómica: la voluntad." Albert Einstein

santilococo

surbyte, buenas noches
lo acabo de probar al codigo y no me anduvo: empieza siempre con el relay encendido, trate de cambiarle los HIGH y LOW pero sigue haciendo lo mismo... es muy raro. Lo que si que no te habia dicho: el relay se enciende cuando esta en LOW. Saludos
"Hay una fuerza motriz más poderosa que el vapor, la electricidad y la energía atómica: la voluntad." Albert Einstein

surbyte

Las cosas funcionan cuando todas las condiciones son correctas.
Verificaste que el pulsador actúe como se espera?
Lo conectaste entre GND y el PIN3?

Prueba con esto

Code: [Select]
//Librerias
#include <Time.h>
#include <TimeAlarms.h>
#include <DS1307RTC.h>
#include <Wire.h>
#include <EEPROM.h>

//Definimos variables
int electro_in1         = 12;
int electro_in2         = 11;

byte sensorInterrupt    = 0;  // 0 = digital pin 2
const byte sensorPin    = 2;
const byte pulsadorPin  = 3;    // conectar aqui el pulsador entre pin y GND
float calibrationFactor = 7.5;
volatile unsigned int pulseCount;  
float flowRate;
float totalLitres;
unsigned long oldTime;
bool estado, estadoAnt = false;

float volumen = 0;
float volumenMaximo = 5; //CAMBIAR ESTO DEPENDIENDO LOS LITROS MÁXIMOS
bool flag = false;

void pulseCounter()
{
  // Increment the pulse counter
  pulseCount++;
}



void setup() {
   // Initialize a serial connection for reporting values to the host
  Serial.begin(9600);
  
  // Set up the status LED line as an output
  pinMode(electro_in1, OUTPUT);
  pinMode(electro_in2, OUTPUT);
  digitalWrite(electro_in1, HIGH);
  digitalWrite(electro_in2, HIGH);
  
  pinMode(sensorPin, INPUT);
  pinMode(pulsadorPin, INPUT_PULLUP);  // pulsador entre pin 3 y GND.

  pulseCount        = 0;
  flowRate          = 0.0;
  totalLitres       = 0.0;
  oldTime           = 0;
  
  // The Hall-effect sensor is connected to pin 2 which uses interrupt 0.
  // Configured to trigger on a FALLING state change (transition from HIGH
  // state to LOW state)
  attachInterrupt(sensorInterrupt, pulseCounter, FALLING);

  //Para el RTC
  setSyncProvider(RTC.get);
  Alarm.alarmRepeat(00, 28, 10, ReiniciarVolumen);  // Evento diario, podriamos ponerla a las 00,00,01. ESTO ME GUSTARIA CAMBIAR
  
}

void loop() {

    estado = digitalRead(pulsador);

    if (estado && estadoAnt) {
        flag = true;

    }
    estadoAnt = estado;

    if (volumen < volumenMaximo)
        if ((millis() - oldTime) > 1000)  {  // Only process counters once per second
            detachInterrupt(sensorInterrupt);
            flowRate = ((1000.0 / (millis() - oldTime)) * pulseCount) / calibrationFactor;
            
            
            // Add the millilitres passed in this second to the cumulative total
            totalLitres += flowRate / 60;
            volumen = totalLitres;
              
            // unsigned int frac;
            Serial.print ("Caudal: ");
            Serial.print (flowRate,3);
            Serial.print ("L/min\tVolumen: ");
            Serial.print (volumen,3);
            Serial.println (" L");

            if (volumen > volumenMaximo ){ /* boton apretado && */
                flag = true;
            }
            
            // Reset the pulse counter so we can start incrementing again
            pulseCount = 0;
            
            // Enable the interrupt again now that we've finished sending output
            attachInterrupt(sensorInterrupt, pulseCounter, FALLING);  
            oldTime = millis();
        }

    if (flag)
        ControlValvula();

    Alarm.delay(1000);
}


// de las alarmas!!!
void ReiniciarVolumen() {
  flag = true;
}

void ControlValvula() {
  //Aca podria ir lo del boton para iniciar la electrovalvula
  if (flag) {
      digitalWrite(electro_in1, LOW);
      digitalWrite(electro_in2, LOW);
      flag = false;
  }
  else {
      digitalWrite(electro_in1, HIGH);
      digitalWrite(electro_in2, HIGH);
  }
}

santilococo

Hola, ahi anda 10 puntos. El problema es que no se apaga nunca la electrovalula (el relay). Probe cambiando flag a false, sacandolo del if, etcetera pero nunca se apaga (llega al limite y sigue tirando agua). Saludos!
"Hay una fuerza motriz más poderosa que el vapor, la electricidad y la energía atómica: la voluntad." Albert Einstein

santilococo

Ahí le cambie un par de cosas y anduvo. Lo que no esta haciendo es que si se desconecta puedo usar 5L de nuevo, se podría guardar Volumen como variable en la EEPROM? o como se haria para que guarde o verifique volumen de antes (con volumen me refiero a cantidad de litros usada). Saludos, grande surbyte!!

Code: [Select]

//Librerias
#include <Time.h>
#include <TimeAlarms.h>
#include <DS1307RTC.h>
#include <Wire.h>
#include <EEPROM.h>

//Definimos variables
int electro_in1         = 12;
int electro_in2         = 11;

byte sensorInterrupt    = 0;  // 0 = digital pin 2
const byte sensorPin    = 2;
const byte pulsadorPin  = 3;    // conectar aqui el pulsador entre pin y GND
float calibrationFactor = 7.11;
volatile unsigned int pulseCount; 
float flowRate;
float totalLitres;
unsigned long oldTime;
bool estado, estadoAnt = false;

float volumen = 0;
float volumenMaximo = 1; //CAMBIAR ESTO DEPENDIENDO LOS LITROS MÁXIMOS
bool flag = false;

void pulseCounter()
{
  // Increment the pulse counter
  pulseCount++;
}



void setup() {
   // Initialize a serial connection for reporting values to the host
  Serial.begin(9600);
   
  // Set up the status LED line as an output
  pinMode(electro_in1, OUTPUT);
  pinMode(electro_in2, OUTPUT);
  digitalWrite(electro_in1, HIGH);
  digitalWrite(electro_in2, HIGH);
 
  pinMode(sensorPin, INPUT);
  pinMode(pulsadorPin, INPUT_PULLUP);  // pulsador entre pin 3 y GND.

  pulseCount        = 0;
  flowRate          = 0.0;
  totalLitres       = 0.0;
  oldTime           = 0;
 

  attachInterrupt(sensorInterrupt, pulseCounter, FALLING);

  //Para el RTC
  setSyncProvider(RTC.get);
  Alarm.alarmRepeat(10, 28, 10, ReiniciarVolumen);  // Evento diario, podriamos ponerla a las 00,00,01. ESTO ME GUSTARIA CAMBIAR
 
}

void loop() {

    estado = digitalRead(pulsadorPin);

    if (estado && estadoAnt) {
        flag = true;

    }
    estadoAnt = estado;

    if (volumen < volumenMaximo)
        if ((millis() - oldTime) > 1000)  {  // Only process counters once per second
            detachInterrupt(sensorInterrupt);
            flowRate = (((1000.0) / (millis() - oldTime)) * pulseCount) / calibrationFactor;
           
           
            // Add the millilitres passed in this second to the cumulative total
            totalLitres += flowRate / 60;
            volumen = totalLitres;
             
            // unsigned int frac;
            Serial.print ("Caudal: ");
            Serial.print (flowRate,3);
            Serial.print ("L/min\tVolumen: ");
            Serial.print (volumen,3);
            Serial.println (" L");
           
            // Reset the pulse counter so we can start incrementing again
            pulseCount = 0;
           
            // Enable the interrupt again now that we've finished sending output
            attachInterrupt(sensorInterrupt, pulseCounter, FALLING); 
            oldTime = millis();
        }

/* LE SAQUE ESTO, NO HACIA NADA
     if (volumen >= volumenMaximo ){
       flag = false;
     }

*/
             
    if (flag)
        ControlValvula();

    Alarm.delay(1000);
}


// de las alarmas!!!
void ReiniciarVolumen() {
  flag = true;
}

void ControlValvula() {
 // if (flag) { (CON ESTO NO ANDA, PORQUE SERA? MI HIPOTESIS ES QUE UNA VEZ QUE ARRANCA LA ELECTROVALVULA EL FLAG NO SE ACTUALIZA, ESTO ES MUY RARO)
   
if (volumen <= volumenMaximo ) { 
      digitalWrite(electro_in1, LOW);
      digitalWrite(electro_in2, LOW);
      //flag = false;
  }
  else {
      digitalWrite(electro_in1, HIGH);
      digitalWrite(electro_in2, HIGH);
  }
}
"Hay una fuerza motriz más poderosa que el vapor, la electricidad y la energía atómica: la voluntad." Albert Einstein

surbyte

#7
Nov 18, 2018, 10:06 pm Last Edit: Nov 19, 2018, 04:01 am by surbyte Reason: Codigo modificado
Prueba con esto desde el loop lo demás igual

Code: [Select]
void loop() {

    estado = digitalRead(pulsadorPin);

    if (estado && !estadoAnt) {
        flag = true;

    }
    estadoAnt = estado;

    if (volumen < volumenMaximo)
        if ((millis() - oldTime) > 1000)  {  // Only process counters once per second
            detachInterrupt(sensorInterrupt);
            flowRate = (((1000.0) / (millis() - oldTime)) * pulseCount) / calibrationFactor;
            
            
            // Add the millilitres passed in this second to the cumulative total
            totalLitres += flowRate / 60;
            volumen = totalLitres;
              
            // unsigned int frac;
            Serial.print ("Caudal: ");
            Serial.print (flowRate,3);
            Serial.print ("L/min\tVolumen: ");
            Serial.print (volumen,3);
            Serial.println (" L");
            
            // Reset the pulse counter so we can start incrementing again
            pulseCount = 0;
            
            // Enable the interrupt again now that we've finished sending output
            attachInterrupt(sensorInterrupt, pulseCounter, FALLING);  
            oldTime = millis();
        }

  if (volumen >= volumenMaximo )
       flag = false;    

  if (flag)
      ControlValvula(LOW);
  else
      ControlValvula(HIGH);

  Alarm.delay(1000);
}


// de las alarmas!!!
void ReiniciarVolumen() {
  flag = true;
}

void ControlValvula(bool tmp) {
      digitalWrite(electro_in1, tmp);
      digitalWrite(electro_in2, tmp);
}

santilococo

Que arreglaste ahi? También donde podria poner otro flag para que cuando toque el boton devuelta se apague la electrovalvula? Suponete si quiero usar 0.5 L ahora y en un rato el resto. Sabes? porque podriamos poner lo de "bool estado" pero donde lo pondriamos? Saludos
"Hay una fuerza motriz más poderosa que el vapor, la electricidad y la energía atómica: la voluntad." Albert Einstein

santilococo


Le saque el principio del void loop
Code: [Select]

void loop() {

    estado = digitalRead(pulsadorPin);

    if (estado && estadoAnt) {
        flag = true;

    }
    estadoAnt = estado;


y le puse esto

Code: [Select]
  if (digitalRead(pulsadorPin)){          // Cuando el pulsador está activo...
   estado = !estado;  // Asigna el valor contrario (ON --> OFF --> ON --> OFF...)
 }

if(estado){        // si Valor_pulsador es Verdadero --> 1 --> ON
 flag = true;    // Enciende el Led
 }
 else {                    // De lo contrario
 flag = false;   // Apaga el Led
 }
 


me funciono ahi apagar y volver a encender, como si fuera un interruptor. esta bien no?
"Hay una fuerza motriz más poderosa que el vapor, la electricidad y la energía atómica: la voluntad." Albert Einstein

surbyte

Si te funciona estará bien.
Si lo vas a usar de ese modo entonces no uses estado para luego cambiar flag sino hazlo directamente sobre flag

Lo que no me gusta es que

esta accción

Code: [Select]
if (digitalRead(pulsadorPin)){          // Cuando el pulsador está activo...
   estado = !estado;  // Asigna el valor contrario (ON --> OFF --> ON --> OFF...)
 }

cambia estado cada vez que se completa el loop, o sea en un segundo cuantas veces puede cambiar? muchas.
En cambio esto

Code: [Select]
 estado = digitalRead(pulsadorPin);

    if (estado && !estadoAnt) {
        flag = true;

    }
    estadoAnt = estado;


Lo hace solo de 0 1 y si quieres el contrario entonces simplemente agregas esto

 estado = digitalRead(pulsadorPin);

Code: [Select]
   if (estado && !estadoAnt) { // <= revisa porque estadoAnt debe ir con ! antes
       flag = true;

   }
   if (!estado && estadoAnt) {
       flag = true;

   }

   estadoAnt = estado;

Go Up