Como puedo interrumpir un loop?

Muy buenas, soy nuevo en arduino y de momento no tengo más que preguntas, espero encontrar opiniones a todas mis dudas, muchas gracias.

Ire poniendo las preguntas de una en una para no aburrir a los lectores.

Tengo un bucle controlado por una entrada digital, solo se ejecuta si la entrada esta a 1, el caso es que cuando pongo la entrada a 0, el loop no para hasta terminar todas las sentencias que tenga pendientes.

Como puedo interrumpir ese loop en el momento que pongo la entrada a 0?

Gracias por su atención

Un saludo

desabróchate el cinturón a ver si salta la seguridad de la atracción... o ¿no hablas de eso?

Si es de software no veo donde tienes el error

Saludos

PD: no somos adivinos y espero que no te lo tomes a mal

Gracias por contestar, no me he debido explicar bien. lo siento.
Pongo un trocito del código a ver si así se entiende mejor.

if(digitalRead(22)) 
{
  digitalWrite(48,1);
  delay(50);
  digitalWrite(48,0);
  digitalWrite(48,1);
  ....
  ... 
  ....
  etc, etc 
}

Basicamente ese es el codigo, aunque ejecuta muchas más instrucciones, no las pongo todas porque sería muy largo.

El caso es que si se cumple el IF, empieza a ejecutar las instrucciones, cuando termina, vuelve a empezar, todo correcto. Si en un momento dado, cambio el estado de la entrada digital 22 a 0, el programa sigue corriendo hasta llegar al final y ya no vuelve a empezar.

Lo que me gustaria es que el programa pare automaticamente cuando el valor de la entrada digital 22 sea 0, independientemente de las lineas de código que le queden por ejecutar, ósea, que se pare sin tener que esperar que llegue al final.

No sé si me explico.

Gracias.

Hola, no se como esta tu código pero las instrucciones se ejecutan tan rápido que a menos que sean detectadas mediante alguna interrupción es imposible de salir. Te pongo un ejemplo.

#include <Arduino.h>

//Variables globales
uint8_t miBoton = 10; //Boton conectado en el puerto 10 

void setup() // Solo se ejecuta una sola vez al iniciar el microcontrolador
{
pinMode(miBoton,INPUT); // puerto declarado como entrada
}

void loop() // Bucle Infinito
{
  if(digitalRead(miBoton)) // Leo el estado del boton
  {
    /*Mientas este precionado ejecuto estas instrucciones*/
    //Instruccion 1
    //Instruccion 2
    // Se dejo de precionar el boton 
    //Instruccion 3
    //.................
  }

  // Sensor 1
  // Sensor 2
  // Sensor 3
  // .....................
}

Ahora como puedes observar tienes un botón el cual mientras este presionado ejecutara las instrucciones de cuando sea verdadero y si se suelta el botón cuando todavía esta realizando las instrucciones no tiene forma de saber ya que el programa esta todavía ejecutado las acciones cuando este estaba presionado, ahora en la siguiente vez que vuelva a leer el estado del botón ya no esta presionado entonces ya no ejecutara mas las acciones y seguirá con el resto del programa, ahora no se como estará tu código pero como veo de por si que tienes esto:

delay(50);

que claramente es voy a esperar aquí y no hare nada mas hasta que pase esa orden. No te puedo ayudar mas porque no esta muy claro lo que quieres hacer.
Intenta explicar mejor lo que estas intentando realizar, las situaciones en las que tiene que para de realizar las acciones etc.
Adjunta el código completo, utilizando las etiquetas correctas y si el código pasa de las líneas permitidas pasa todo el archivo del código.

Hola:
utiliza una interrupción de harware, Leete en la referencia de arduino la instrupción "attachInterrupt()".
Saludos.

El programa tarda en ejecutarse completo 12 segundos ya que tiene un montón de delays de 50 y de 100, se trata de un secuenciador de luces de emergencia estroboscopicas para un vehiculo de emergencias. Son unas 50 secuencias distintas que se ejecutan una detras de otra. De momento lo he solucionado poniendo un if que compara el estado de la entrada digital despues de cada secuencia, si, es una chapuza, lo intentare con interrupciones, a ver que tal va. Muchas gracias por tus aportes.

Muchas gracias. lo probare

Una interrupción creo que no te va a ayudar porque igual vas a tener que controlar continuamente si se produjo porque no hay forma de cortar el flujo del programa directamente desde una interrupción (o yo no la conozco). Quiero decir, desde una interrupción podrías cambiar el valor de una variable pero igual tienes que controlar si esa variable cambió para salir de la secuencia, o sea, es lo mismo que lo que haces ahora pero más complicado.

Lo que te conviene (para no tener que cambiar el código directamente) es dividir la secuencia en bloques que puedas poner en diferentes rutinas. Por ejemplo, tomas las primeras instrucciones hasta que los delays suman 1 seg y las pones en una rutina, digamos secuencia1(), luego todas las que siguen hasta obtener 1 seg y las pones en secuencia2(), y así hasta el final.
Algo así

void secuencia1() {
  digitalWrite(48,1);
  delay(50);
  digitalWrite(48,0);
  digitalWrite(48,1);
  ....
  ... 
  ....
}

Luego harías algo así

if(digitalRead(22)) {
  secuencia1();
  if(!digitalRead(22)) break;
  secuencia2();
  if(!digitalRead(22)) break; 
  ...
  secuenciaN();
}

Es básicamente lo mismo pero haces menos consultas y el retraso a la respuesta del botón sería de solo un segundo.

Tal vez se pueden usar punteros, poner todo en un array y llamar a las rutinas desde un simple for, pero todavía no llego a eso.

Saludos

Buenos días, exactamente como lo has expuesto es como lo deje ayer, comprobando el estado de la entrada en cada secuencia, asi, cuando cambia el estado, espera a terminar la secuencia y sale, no espera a que corra todo el programa.
Muchas gracias

Entonces entendí cualquier cosa... ::slight_smile:

Saludos

Creo que lo enfocas mal desde el principio. Deberías usar millis con cada pin que uses y así no tendrías problemas de encender y apagar cada pìn en el mili-segundo posterior.

Si son varios los pins (en tu ejemplo solo veo el 48) empieza con millis usando uno. Cuando ese lo tengas todo correcto, pon otro. Cuando recibas un 1 o un 0 simplemente debes poner todas las variables y piuns a 0, algo que costará muy poco en tiempo

Saludos

Buenas tardes, como entradas estoy usando de la 22 a la 30 y como salidas de la 31 a la 53. No entiendo muy bien lo que quieres decir, soy nuevo y estoy muy verde, te agradeceria si me puedes poner un ejemplo.
Gracias

Mejor subí el código completo porque sino vamos a seguir intentando adivinar qué es lo que realmente intentas hacer.

Saludos

Moderador:
Por favor no repitas lo que otra persona te dice. Ya se lee en el post correspondiente.
Menciona a la persona por su nick y nada más.
Usa quote o cita para resaltar el párrafo que respondes. Cuando resaltas todo es cuando cometes la falta.

Corregí tu primer respuesta y luego me encuentro con infinidad de faltas similares.
Deja de hacerlo por favor, y edital todas las que tienen repetición de comentarios.
Gracias.

Cuando postees un código hazlo completo nada de un trocito ni cosas similares. Como tu mismo dices, estas aprendiendo entonces tienes poco criterio para evaluar si dicha porción es suficiente o no. Además nosotros necesitamos siempre ver el código completo para a veces considerar las variables que usas o bien sugerirte cambios que involucran todo el código.

En lo personal usar interrupciones para detener un código mal hecho para mi es una mala idea. He cambiado mi discurso porque antes decía que eran una tontería y me acusaban de decirle tonto. Claro esta que me refería a la que acción no a quien la aplicaba pero por esa razón no lo digo. Es un recurso, claro que lo es pero considero que NO NECESARIO.

Mira como uso yo tus comentarios:

El programa tarda en ejecutarse completo 12 segundos

Justamente tarda 12 segundos por usar delay() y he ahí que cuando quieres hacer otra cosa no puedes por el abuso de delays().
Solución: usar millis(). Este foro solo vive hablando de usar millis() lo que indica que has leído poco el foro pero tienes tiempo.
En Documentación encontrarás buenos tutoriales sobre el uso de millis() y máquiina de estados que es lo que resolverá tu problema

Con una máquina de estados, vas cumpliendo estados o secuencias. Pasas al siguiente si solo si, se han cumplido las condiciones de dicho estado.Pudes saltar al estado que desees,no tiene porqué ser secuencia..
supon una variable que llamo estado del tipo byte o sea que va de 0 a 255. Si tienes mas estados que 256 casos te felicito.

usas un switch case para ir de estado a estado.
Puedes usar por ejemplo algo como

byte estado = 0;

y luego con esto

switch (estado) {
    case 0:  // secuencia 1
                  estado = 1;
                  break;
    case 1: // secuencia 2
                  estado = 2;
                  break;

Las condiciones para pasar de un estado a otro son de lo mas diverso.
Ejemplo como pasar esto

digitalWrite(48,1);
  delay(50);
  digitalWrite(48,0);
  digitalWrite(48,1);

a maquina de estados?

vas a poner que uso una variable estadoSeq1 que previamente definí como byte y la puse a 0.

entonces esos 2 pasos o estados los haría asi.
El delay requiere para su reemplazo de una variable que asociaré con millis(). Llamo a la variable startSeq1 y se define asi.

// en globales defino
unsigned long startSeq1;
byte estadoSeq1 = 0;

//en el loop
switch(estadoSeq1) {
    case 0: digitalWrite(48,1);
                estadoSeq1 = 1;  // aca termina el primer esado porque ya pase a uno el pin 48
                startSeq1 = millis();
                break;                   // enel siguiente ciclo ie a case 1
    case 1: if (millis()-startSeq1 > 50UL) {
                     digitalWrite(48,0);
                     digitalWrite(48,1);
                     estadoSeq1 = 2;
                 }
                 break;

solo son 2 pasos y puede seguir interminablemente, pero acá nada frena el código.
Si fuera de las máquinas de estado, quieres leer un pin, no tienes problemas, lo haces sin perder tiempo.
Pero repito NO USES DELAY en ningún momento y esto fuirá.
Toda la información esta en Documentación => Indice de temas tutoriales.

Hola a todos.

Creo que todos llevamos razón en lo que hemos posteado, pero yo en particular aún no entiendo muy bien lo que quiere hacer nuestro amigo @gontzal323, ya que no ha puesto el código completo y me preocupa esas líneas de los sensores....
Así que por favor @gontzal323 contéstame solo con si o no : ¿para lo que quieres hacer seria igual que pulsar fisicámente el botón del RESET de la placa cuando estas dentro del IF ?.

Saludos chicos.

void setup() {

//Entradas

pinMode(22, INPUT);  //Interruptor rotativos
pinMode(23, INPUT);  //Interruptor luces carretera
pinMode(24, INPUT);  //Intermitente derecho
pinMode(25, INPUT);  //Intermitente izquierdo
pinMode(26, INPUT);  //Freno
pinMode(27, INPUT);  //Toma fuerza
pinMode(28, INPUT);  //Luces de servicio

//Salidas

pinMode(30, OUTPUT); //Rotativos
pinMode(31, OUTPUT);
pinMode(32, OUTPUT);
pinMode(33, OUTPUT);
pinMode(34, OUTPUT);
pinMode(35, OUTPUT);
pinMode(36, OUTPUT);
pinMode(37, OUTPUT);
pinMode(38, OUTPUT);
pinMode(39, OUTPUT);
pinMode(40, OUTPUT);
pinMode(41, OUTPUT);
pinMode(42, OUTPUT);
pinMode(43, OUTPUT);
pinMode(44, OUTPUT);
pinMode(45, OUTPUT);
pinMode(46, OUTPUT);
pinMode(47, OUTPUT); // Fin Rotativos
pinMode(48, OUTPUT); // Estrobos cabina
pinMode(49, OUTPUT); // Estrobos calandra
pinMode(50, OUTPUT); // Toma Fuerza
pinMode(51, OUTPUT); // Luces de servicio delanteras
pinMode(52, OUTPUT); // Luces de servicio plataforma
pinMode(53, OUTPUT); // Luces de servicio palas
}

void loop() {

if(digitalRead(22)){ //rotativos encendidos

digitalWrite(48,1);
delay(50);
digitalWrite(48,0);
digitalWrite(48,1); // Estrobos calandra

}

 //Primera secuencia

if(digitalRead(22)){
  
for(int i=0;i<10;i++)
{
   
digitalWrite(30,HIGH);
digitalWrite(31,HIGH);
digitalWrite(32,HIGH);
digitalWrite(33,HIGH);
digitalWrite(34,HIGH);
digitalWrite(35,HIGH);
digitalWrite(36,HIGH);
digitalWrite(37,HIGH);
digitalWrite(38,HIGH);

digitalWrite(39,LOW);
digitalWrite(40,LOW);
digitalWrite(41,LOW);
digitalWrite(42,LOW);
digitalWrite(43,LOW);
digitalWrite(44,LOW);
digitalWrite(45,LOW);
digitalWrite(46,LOW);
digitalWrite(47,LOW);

delay(100);

digitalWrite(30,LOW);
digitalWrite(31,LOW);
digitalWrite(32,LOW);
digitalWrite(33,LOW);
digitalWrite(34,LOW);
digitalWrite(35,LOW);
digitalWrite(36,LOW);
digitalWrite(37,LOW);
digitalWrite(38,LOW);

digitalWrite(39,HIGH);
digitalWrite(40,HIGH);
digitalWrite(41,HIGH);
digitalWrite(42,HIGH);
digitalWrite(43,HIGH);
digitalWrite(44,HIGH);
digitalWrite(45,HIGH);
digitalWrite(46,HIGH);
digitalWrite(47,HIGH);

delay(100);
}

digitalWrite(39,LOW);
digitalWrite(40,LOW);
digitalWrite(41,LOW);
digitalWrite(42,LOW);
digitalWrite(43,LOW);
digitalWrite(44,LOW);
digitalWrite(45,LOW);
digitalWrite(46,LOW);
digitalWrite(47,LOW);

}

 //Segunda secuencia
 
if(digitalRead(22)){
  
for(int i=0;i<3;i++)
{

for(int b=0;b<5;b++)
{

digitalWrite(30,HIGH);
digitalWrite(31,HIGH);

delay(50);

digitalWrite(30,LOW);
digitalWrite(31,LOW);

delay(50);
}

for(int b=0;b<5;b++)
{
digitalWrite(32,HIGH);
digitalWrite(33,HIGH);

delay(50);

digitalWrite(32,LOW);
digitalWrite(33,LOW);
delay(50);
}
}
}

 //tercera secuencia

if(digitalRead(22)){
  
for(int c=0;c<5;c++)
{
digitalWrite(30,HIGH);
digitalWrite(31,HIGH);
digitalWrite(32,HIGH);
digitalWrite(33,HIGH);
delay(100);
digitalWrite(30,LOW);
digitalWrite(31,LOW);
digitalWrite(32,LOW);
digitalWrite(33,LOW);
delay(100);
}
}

 //cuarta secuencia
 
if(digitalRead(22)){
  
for(int i=0;i<3;i++)
{
for(int d=0;d<5;d++)
{
digitalWrite(30,HIGH);
digitalWrite(33,HIGH);
delay(50);
digitalWrite(30,LOW);
digitalWrite(33,LOW);
delay(50);
}

for(int d=0;d<5;d++)
{
digitalWrite(31,HIGH);
digitalWrite(32,HIGH);
delay(50);
digitalWrite(31,LOW);
digitalWrite(32,LOW);
delay(50);
}
} 
}

//si se encienden las luces y no estan encendidos los rotativos

if(digitalRead(25) && !digitalRead(22)){

digitalWrite(30,1);
digitalWrite(31,1);
digitalWrite(32,1);
digitalWrite(33,1);
digitalWrite(34,1);
digitalWrite(35,1);
digitalWrite(36,1);
digitalWrite(37,1);
digitalWrite(38,1);
digitalWrite(39,1);
digitalWrite(40,1);
digitalWrite(41,1);
digitalWrite(42,1);
digitalWrite(43,1);
digitalWrite(44,1);
digitalWrite(45,1);
digitalWrite(46,1);
digitalWrite(47,1);

}

else

{

digitalWrite(30,0);
digitalWrite(31,0);
digitalWrite(32,0);
digitalWrite(33,0);
digitalWrite(34,0);
digitalWrite(35,0);
digitalWrite(36,0);
digitalWrite(37,0);
digitalWrite(38,0);
digitalWrite(39,0);
digitalWrite(40,0);
digitalWrite(41,0);
digitalWrite(42,0);
digitalWrite(43,0);
digitalWrite(44,0);
digitalWrite(45,0);
digitalWrite(46,0);
digitalWrite(47,0);

}  

//intermitente izquierdo

if(!digitalRead(22)){

while(digitalRead(25))
  {

if(digitalRead(22))break;
    
digitalWrite(38,1);
delay(150);
digitalWrite(37,1);
delay(150);
digitalWrite(36,1);
delay(150);
digitalWrite(35,1);
delay(150);
digitalWrite(34,1);
delay(150);
digitalWrite(33,1);
delay(150);
digitalWrite(32,1);
delay(150);
digitalWrite(31,1);
delay(150);
digitalWrite(30,1);
delay(150);

digitalWrite(38,0);
digitalWrite(37,0);
digitalWrite(36,0);
digitalWrite(35,0);
digitalWrite(34,0);
digitalWrite(33,0);
digitalWrite(32,0);
digitalWrite(31,0);
digitalWrite(30,0);
  }
  }
}

He acortado el código porque es muy repetitivo y todas las sencuencias son estructuralmente iguales, solo cambia el orden y tiempos en que se activan las salidas . Siento lo de los quotes, pensaba que haciendolo así era más fluida la conversación, no se volverá a repetir.

Hola @gontsal323.
Pues según el código que has puesto ya lo has resuelto, coloca la linea que has pueto del break delante de cada secuencia. Algo tedioso sin son muchas, pero efectivo.
Saludos.

Si, esta resuelto, pero me parece un poco chapuza, me estoy estudiando los millis que me parece mejor ya que en ningún momento se interrumpe el código y se puede interactuar con las entradas mucho más rápido, creo que va a ser más efectivo que los delays.

Moderador:
No te pedí algo por privado?
digo porque sigo sin ver que hayas hecho las modificaciones.
Responde por privado

This topic was automatically closed 120 days after the last reply. New replies are no longer allowed.