Código con Interrupciones no funcionan temporizaciones..

Necesito leer los pulsos de un contador de agua y en función de estos activar 3 bombas dosificadoras de aditivos durante un tiempo determinado para cada una.

Según he leído lo mejor es utilizar interrupciones para que no perder los pulsos.

He intentado con diferentes formas de temporizar si se cumplen un determinado nº de pulsos, y la rutina funciona correctamente, pero si recibo un pulso en mitad de la rutina deja de funcionar...

Este es el código. Un saludo y gracias..

//-------------------------------------------------- //Declara puertos de entradas y salidas y variables //-------------------------------------------------- // Botones const int BTN1 = 18; const int BTN2 = 19; const int BTN3 = 20;

const int ledverde = 53; //Le ponemos nombre al pin 13 const int ledrojo = 49; //Le ponemos nombre al pin 13 const int ledamarillo = 51; //Le ponemos nombre al pin 13

const int POT = 2;

volatile long lastInt; // Tiempo en que se realizo la última interrupción.

int contador = 0; //Variable para guardar la cuenta de pulsaciones int valorPOT = 0; //int estadoAnteriorBoton = 0; //Declaramos e inicializamos la variable //int valorBoton = 0; //Declaramos e inicializamos la variable //------------------------------------ //Funcion principal //------------------------------------ void setup() // Se ejecuta cada vez que el Arduino se inicia { Serial.begin(9600); //Inicia comunicación serie pinMode(ledverde,OUTPUT); //Configura el pin como una salida, LED pinMode(ledrojo,OUTPUT); //Configura el pin como una salida, LED lastInt = 0;

// Asociamos la interrupción a nuestro código attachInterrupt(5,int5,RISING); // línea 18 attachInterrupt(4,int4,RISING); // línea 19 //attachInterrupt(3,int3,RISING); // línea 20 } // Incrementa y escribe el número al display void increment() { contador++; //Aumentamos en una unidad la cuenta Serial.print("Contador=");Serial.println(contador); //Imprime el valor por consola digitalWrite(ledverde,HIGH); //Encendemos el led delay (10000); digitalWrite(ledverde,LOW); //Encendemos el led} //valorPOT = analogRead(POT)*10; //Serial.print("// ValorPOT=");Serial.println(valorPOT); //Imprime el valor por consola //if(contador>5){contador=0;} //Aumentamos en una unidad la cuenta }

// Decrementa y escribe el número al display void decrement() { contador--; //Aumentamos en una unidad la cuenta Serial.print("Contador="); Serial.println(contador); //Imprime el valor por consola digitalWrite(ledrojo,HIGH); //Encendemos el led} delay (10000); digitalWrite(ledrojo,LOW); //Encendemos el led} }

void int5() { if((millis()-lastInt)>400) { increment(); lastInt = millis(); } }

void int4() { if((millis()-lastInt)>400) { decrement(); lastInt = millis(); } } // Loop vacío void loop() {

if(contador==5){ valorPOT = analogRead(POT)*10; //Serial.print("ValorPOT=");Serial.println(valorPOT); //Imprime el valor por consola digitalWrite(ledrojo, HIGH); // enciende el pin 13 Serial.println((millis()-lastInt)); if((millis()-lastInt)>valorPOT) { digitalWrite(ledrojo, LOW); // apaga el pin 13 Serial.print("ContadorReset="); contador=0; //Aumentamos en una unidad la cuenta Serial.println(contador); //Imprime el valor por consola } } }

Saludos Ante todo cuando vas a colocar tu código en la parte superior hay un icono con el # persona alli y te aparece "["code] [/code"]" y en medio colocas el codigo.

Ahora en toda interrupcion la accion que se este ejecutando es detenida, incluso los temporizadores, para atender la interrupcion. Y el tiempo que tarda em colocarse en movimiento nuevamente depende de lo que hagas durante esa interrupcion. Eso es lo normal. Si que para reducir el tiempo de inactividad debes hacer un código sencillo y básico para atender la interrupcion.

Lo primero que veo es un error conceptual en el uso de las interrupciones y los temporizadores. Una interrupción es una rutina RAPIDA que precisamente puede atender este tipo de cosas.. cada pulso que ocurra. De ningún modo una interrupción puede tener un retardo de 10 segundos en su interior, es inadmisible. Asi que la interrupción debe incrementar los contadores para conocer el caudal y los temporizadores deben ser externos a estas rutinas. Lo que yo haria es algo muy simple. Manejar variables bool que lleven el estado de los temporizaodores incrementar o decrementar Ademas veo muchos errores en el codigo.

usa esto

unsigned long TimerA   
unsigned long TimerB  
bool accion1 = false;
bool accion2 = false;

if (accion1) {
    TimerA= millis();                               // usar accion1 = false aqui permite redisparos cada 400 mseg
   accion1 = false;
    digitalWrite(ledverde,HIGH);
}
if (millis()-TimerA >= 10000UL) {
    digitalWrite(ledverde, LOW);
    //accion1 = false;                                 // donde ubiques esta linea te dará el control para poder tomar nuevos disparos o solo 1.
}

if (accion2) {
    TimerA= millis();
   accion2 = false;
    digitalWrite(ledrojo,HIGH);
   }
if (millis()-TimerA >= 10000UL) {
    digitalWrite(ledrojo, LOW);
   // accion2 = false;              // mismo criterio que anterior.
}

accion1 y 2 esta dentro de las interrupciones de este modo

void int5() { if((millis()-lastInt)>400) { accion1 = true; lastInt = millis(); // esto no se si debería ir aquí. Falta analizarlo }

Esto es orientativo, aun le falta trabajo.

Gracias por contestar; He organizado mejor el código y realizado una conexión con excel par monitorizar como funciona, pero no consigo que funcione, me funciona una de las interrupciones pero las otras no y siempre es la misma la (1), o me enciende aleatoria-mente otros led, me falla algo y ya he probado a cambiar codigo nombres y todo lo que se me ocurre.

Pongo el código por si lo podeis mirar. Gracias y un saludo..

   //-------------------------------------------------------------------------------------------
        //Declara puertos de entradas y salidas
        //-------------------------------------------------------------------------------------------
        
        // Botones Asociados a Interrupcciones (Posteriormente conectaremos los contadores de pulsos)
        const int BTN1= 18;         //Le ponemos nombre a la interrupccion pin 18
        const int BTN2= 19;         //Le ponemos nombre a la interrupccion pin 19
        const int BTN3= 21;         //Le ponemos nombre a la interrupccion pin 20
        
        // Led salidas (Posteriormente conectaremos las bombas aditivos)
        const int ledR = 49;        //Salida Marcha Bomba 3
        const int ledA = 51;        //Salida Marcha Bomba 2
        const int ledV = 53;        //Salida Marcha Bomba 1
        
        // Entrada Analogica Potenciomentro(Prog. Temporizadores Marcha Bombas)
        const int POT_B1 = A2;       //Entrada Analogica Potenciometro Timer Marcha Bomba 1
        const int POT_B2 = A3;       //Entrada Analogica Potenciometro Timer Marcha Bomba 2
        const int POT_B3 = A4;       //Entrada Analogica Potenciometro Timer Marcha Bomba 3
        
        const int POT_AGUA = A1;     //Entrada Analogica Potenciomentro(M3_Agua Ciclos)
        
        //-------------------------------------------------------------------------------------------
        //Declara variables
        //-------------------------------------------------------------------------------------------
        
        volatile long lastInt_B1 =0; // Tiempo en que se realizo la última interrupción.
        volatile long lastInt_B2= 0;
        volatile long lastInt_B3= 0;
        
        int contador_C1 = 0;  //Variable para guardar la cuenta de pulsaciones del contador
        int contador_C2 = 0;  //Variable para guardar la cuenta de pulsaciones del contador
        int contador_C3 = 0;  //Variable para guardar la cuenta de pulsaciones del contador
        
        int SP_M3_AGUA = 0; // Variable para guardar programacion de pulsos desde potenciometro agua
        
        int row = 0; // Nº Fila para comunicaion Excel Parallax
        
        int SP_Timer_B1 = 0; //Variable para guardar programacion potenciomentro temporizacion marcha bombas
        int SP_Timer_B2 = 0;
        int SP_Timer_B3 = 0;
        
        int Marcha_B1 = 0; // Estado Bombas Marcha(1)/Paro(0)
        int Marcha_B2 = 0;
        int Marcha_B3 = 0;
        
        int Resto_Marcha_B1 = 0; //tiempo regresivo para parada de bomba
        int Resto_Marcha_B2 = 0;
        int Resto_Marcha_B3 = 0;
        
        long Inicio_Timer_B1=0; // Variable que almacena millis() de incio de marcha bombas
        long Inicio_Timer_B2=0;
        long Inicio_Timer_B3=0;
        
        
        //-------------------------------------------------------------------------------------------
        //Funcion principal
        //-------------------------------------------------------------------------------------------
        // Se ejecuta cada vez que el Arduino se inicia
        void setup() 
        {
        Serial.begin(9600);   //Inicia comunicación serie
        Serial.println("CLEARDATA");
        Serial.println("LABEL,Time,SP_M3_Agua,Contador_C1,SP_Timer_B1,Marcha_B1,Resto_Marcha_B1,Contador_C2,SP_Timer_B2,Marcha_B2,Resto_Marcha_B2,Contador_C3,SP_Timer_B3,Marcha_B3,Resto_Marcha_B3");
        
        pinMode(ledV, OUTPUT);   //Configura el pin como una salida, LED
        pinMode(ledR, OUTPUT);   //Configura el pin como una salida, LED
        pinMode(ledA, OUTPUT);   //Configura el pin  como una salida, LED
        
        lastInt_B1 = 0;
        lastInt_B2 = 0;
        lastInt_B3 = 0;
        
        // Asociamos la interrupción a nuestro código
        
        attachInterrupt(1, INTE1, RISING); // Patilla 21 Boton debajo led amarillo
        attachInterrupt(2, INTE2, RISING); // Patilla 19 Boton debajo led amarillo
        attachInterrupt(3, INTE3, RISING); // Patilla 18 Boton debajo led Verde
        }
        
        void INTE1() { if((millis()-lastInt_B1)>400) {increment_C1();lastInt_B1 = millis();}}
        void INTE2() { if((millis()-lastInt_B2)>400) {increment_C2();lastInt_B2 = millis();}}
        void INTE3() { if((millis()-lastInt_B3)>400) {increment_C3();lastInt_B3 = millis();}}
        
        
        // Incrementa y escribe el número al display
        void increment_C1() {contador_C1++; digitalWrite(ledV,HIGH); delay(10000); digitalWrite(ledV,LOW);}
        void increment_C2() {contador_C2++; digitalWrite(ledA,HIGH); delay(10000); digitalWrite(ledA,LOW);}
        void increment_C3() {contador_C3++; digitalWrite(ledR,HIGH); delay(10000); digitalWrite(ledR,LOW);}  
        
        
        // Loop vacío
        void loop(){
        
        SP_Timer_B1= analogRead(POT_B1)*10; //Lectura Potenciometro B1
        SP_Timer_B2= analogRead(POT_B2)*10; //Lectura Potenciometro B2
        SP_Timer_B3= analogRead(POT_B3)*10; //Lectura Potenciometro B3 (NO TENGO MAS POT LE ASIGNO UN NUMERO)
        //SP_Timer_B3= 5000;
        SP_M3_AGUA= int(analogRead(POT_AGUA)/10); // Entrada Analogica Potenciomentro(Prog. m3 Agua Ciclos Temporizacion)
        
        Serial.print("DATA,TIME,");
        Serial.print(SP_M3_AGUA,DEC);
        Serial.print(",");Serial.print(contador_C1);Serial.print(",");Serial.print(SP_Timer_B1,DEC);Serial.print(",");Serial.print(Marcha_B1,DEC);Serial.print(",");Serial.print(Resto_Marcha_B1,DEC);
        Serial.print(",");Serial.print(contador_C2);Serial.print(",");Serial.print(SP_Timer_B2,DEC);Serial.print(",");Serial.print(Marcha_B2,DEC);Serial.print(",");Serial.print(Resto_Marcha_B2,DEC);
        Serial.print(",");Serial.print(contador_C3);Serial.print(",");Serial.print(SP_Timer_B3,DEC);Serial.print(",");Serial.print(Marcha_B3,DEC);Serial.print(",");Serial.println(Resto_Marcha_B3,DEC);
        
        if(contador_C1==SP_M3_AGUA){ Marcha_B1=1; Inicio_Timer_B1=millis(); contador_C1=0;}
        if(Marcha_B1==1){digitalWrite(ledV, HIGH);
            //Resto_Marcha_B1= SP_Timer_B1 - (millis()-Inicio_Timer_B1);
            if((millis()-Inicio_Timer_B1)>SP_Timer_B1){
            Marcha_B1=0;
            digitalWrite(ledV, LOW);
            Resto_Marcha_B1=0;
            }  
        }
        
        if(contador_C2==SP_M3_AGUA){ Marcha_B2=1; Inicio_Timer_B2=millis(); contador_C2=0;}
        if(Marcha_B2==1){digitalWrite(ledA, HIGH);
            //Resto_Marcha_B2= SP_Timer_B2 - (millis()-Inicio_Timer_B2);
            if((millis()-Inicio_Timer_B2)>SP_Timer_B2){
            Marcha_B2=0;
            digitalWrite(ledA, LOW);
            Resto_Marcha_B2=0;
            }  
        }
        
        if(contador_C3==SP_M3_AGUA){ Marcha_B3=1; Inicio_Timer_B3=millis(); contador_C3=0;}
        if(Marcha_B3==1){digitalWrite(ledR, HIGH);
            //Resto_Marcha_B3= SP_Timer_B3 - (millis()-Inicio_Timer_B3);
            if((millis()-Inicio_Timer_B3)>SP_Timer_B3){
            Marcha_B3=0;
            digitalWrite(ledR, LOW);
            Resto_Marcha_B3=0;
            }  
        }
        
        Serial.println("ROW,SET,2");
        delay(100);  
        }

No se si sigues con tu código pero encuentro que solo una interrupción esta funcionando bien.
La INT 2, ahora busco porque no responden 1 y 3. Si se debe a los pines asignados (lo mas probable) o si hay otra razón.
verifico y actualizo esta respuesta

Bueno investigando un poco leo esto

Donde Mega
int 1 es pin 3
int 2 es pin 21 LA QUE FUNCIONA
int 3 es pin 20

De modo que como usaré PIN 21, 19 y 18 voy a cambiar los que estan mal.
respetando tus elecciones.

Ahora el código trabaja como esperabas, mas alla si todo lo demás funcione bien, las interrupciones se activan y los contadores avanzan con cada cambio.

Interrupciones.ino (6.38 KB)

Me acabo de dar cuenta que el código dentro de cada función llamada por las interrupciones esta mal. Jamás puedes detener una interrupción con un delay asi que como máximo activas una variable bool y externamente prendes y apabas los leds indicando el disparo.