Codigo de interrupcion con boton y dos leds

Tengo una duda con las interrupciones puesto que estoy usando el siguiente codigo:

const int emuPin = 10;
const int LED = 13;
const int intPin = 2;
volatile int state = LOW;
 
void setup() {
   pinMode(emuPin, OUTPUT);
   pinMode(LED, OUTPUT);
   pinMode(intPin, INPUT);//RESISTENCIA PULL_DOWN
   attachInterrupt(digitalPinToInterrupt(intPin), switchPressed, CHANGE);
}
 
void loop() {
   //esta parte es para emular la salida
   digitalWrite(emuPin, HIGH);
   delay(150);
   digitalWrite(emuPin, LOW);
   delay(150);
}
 
void switchPressed() {
   if (digitalRead (intPin) == HIGH){
    digitalWrite (LED, HIGH);
    delayMicroseconds(2000);
   }else{
    digitalWrite (LED, LOW);
   }
}

Donde en el void loop solo parpadea un led digamos eternamente, y el el void switchPressed que hace la interrupcion intento que un segundo led encienda durante dos segundos por medio de un boton pero solo enciende mientras presiono el boton, no se si podrian apoyarme quiza es un error de la programacion que no haya entendido

delayMicroseconds(2000);

Son 2 milisegundos, no 2 segundos.

Pero lo más importante: No puedes usar delays dentro de una rutina de servicio de interrupción.

Lectura recomendada:
https://www.gammon.com.au/interrupts

1 Like

Perdona pero no termino de entender como usar el tiempo, es decir que utilizo para encender ese led dos segundos

Para empezar no usar interrupciones para leer un botón.
Para controlar tiempo usas millis().

Sigue los ejemplos de la IDE de Arduino, es la mejor manera ir entendiendo paso a paso.

Mira BlinkwithoutDelay.ino del IDE.

Hola sigo batallando intentando hacer el reinicio de los millis, la diferencia es que ahora ya he comprendido un poco mas pero aun asi sigo sin poder hacer eso ya para terminar mi proyecto. El codigo va algo asi:

#include <Servo.h>
#include <Wire.h> 
#include <LiquidCrystal_I2C.h>

LiquidCrystal_I2C lcd(0x3F,16,2);
unsigned long tiempo1 = 0;
unsigned long tiempo2 = 0;
unsigned long tiempoSegundos = 0;
const int Trigger = 7;
const int Echo = 6;
int led2 = 13;
int led = 10;
int p1 = 3;
int p2 = 2;
Servo myservo;

void setup() {
  myservo.attach(9);
  Serial.begin(9600);
  tiempo1 = millis();
  lcd.init();
  lcd.backlight();
  lcd.print(" Tiempo ");
  pinMode(led,OUTPUT);
  pinMode(led2,OUTPUT);
  pinMode(p1,INPUT);
  pinMode(p2,INPUT);
  pinMode(Trigger, OUTPUT); //pin como salida
  pinMode(Echo, INPUT);  //pin como entrada
  digitalWrite(Trigger, LOW);//Inicializamos el pin con 0
}

void loop() {
  tiempo2 = millis();
  if(tiempo2 - tiempo1 >= 1000){  //Si ha pasado 1 segundo ejecuta el IF
    tiempo1 = millis(); //Actualiza el tiempo actual
    tiempoSegundos = tiempo1/60000; //conversion
    tiempoSegundos = 1 - tiempoSegundos; //Configuracion de tiempo en minutos
    Serial.print("Ha transcurrido: "); 
    Serial.print(tiempoSegundos); 
    Serial.println(" desde que se encendio el Arduino"); 
    Serial.println(tiempo2);
    lcd.setCursor(0,1); 
    lcd.print(tiempoSegundos); 
    lcd.print(" minutos"); 
  }

  long t; //timepo que demora en llegar el eco
  long d; //distancia en centimetros

  digitalWrite(Trigger, HIGH);
  delayMicroseconds(10);          //Enviamos un pulso de 10us
  digitalWrite(Trigger, LOW);
  
  t = pulseIn(Echo, HIGH); //obtenemos el ancho del pulso
  d = t/59;

  if(tiempoSegundos==60000){//intento reiniciar en este punto; cuando llegue al minuto todas las variables se van a 0
    tiempoSegundos=0;
    tiempo1=0;
    tiempo2=0;
  }


  if(tiempo2<30000){//si millis < 30000 enciende un led y el otro lo apaga
   digitalWrite(led2,HIGH);
   digitalWrite(led,LOW);
   myservo.write(55);
   //delay(5000);
 }
  if(tiempo2 > 30000){//si millis > 30000 enciende un led y el otro lo apaga
   digitalWrite(led,HIGH);
   digitalWrite(led2,LOW);
   myservo.write(15);
   //delay(5000);
 }
  if(digitalRead(p2)==HIGH  || d<=35){//si se presiona el pulsador          enciende el led contrario un segundo
   Serial.println("bad");             //o si el sensor detecta algo <35 cm 
   myservo.write(15);
   digitalWrite(led,HIGH);
   digitalWrite(led2,LOW);
   delay(5000);
 }
  if(digitalRead(p1)==HIGH){//si se presiona el pulsador enciende el led contrario un segundo
   Serial.println("nice");
   myservo.write(15);
   digitalWrite(led,LOW);
   digitalWrite(led2,HIGH);
   delay(5000);
 }
}

Mi otra idea de reinicio es hacer una resta, no se si tambien este bie, seria algo asi:

if(tiempoSegundos==60000){//reinicio una vez que sea un minuto
    tiempoSegundos=tiempoSegundos-59000;
    tiempo1=0;
    tiempo2=0;
  }

Me seria de muchisima ayuda, ya es lo ultimo para dejar esto

¿Sabés que si hacés siempre lo mismo el resultado será siempre el mismo, no?

¿Vienes a buscar ayuda o a hacernos perder el tiempo?
Ya te dije más de una vez como debes calcular correctamente el tiempo transcurrido y sigues con la tuya (y lo peor es que te expliqué por qué está mal).

Y si no entiendes, di "No logro entenderlo, alguien me lo puede explicar?" y listo, trataremos de explicarte.

Ok, disculpas por el tirón de orejas.

Por cosas como esta es que se pide no abrir varios temas sobre un mismo problema, para saber que quieres que haga tu código tuve que buscar los temas anteriores. Le voy a pedir a @Surbyte que los una, aguántate el reto.

Vamos a hacer las cosas bien, vamos a ir resolviendo las cosas de a poco, ¿Ok?
Primero vamos por lo de los LED que cambian cada 1 minuto o 30 segundos (no queda clara tu explicación dices una cosa y en el código haces otra)

Vamos a encender los LED alternadamente cada 30 segundos (como dice tu código), los pulsadores los dejamos para después, LCD y SR04 quedan como están.

Como los LED tienen estados opuestos (si uno está encendido el otro está apagado) voy a agregar arbitrariamente una variable que refleja el estado del LED2 (pero podría ser el LED1, solo elegí el 2)

#include <Servo.h>
#include <Wire.h>
#include <LiquidCrystal_I2C.h>

LiquidCrystal_I2C lcd(0x27, 16, 2);
unsigned long tiempo1 = 0;
unsigned long tiempo2 = 0;
unsigned long tiempoSegundos = 0;
const int Trigger = 7;
const int Echo = 6;
int led2 = 13;
int led = 10;
int p1 = 3;
int p2 = 2;
Servo myservo;
bool estadoLED2 = true;  // determina el estado de LED2. true = encendido

void setup() {
  myservo.attach(9);
  Serial.begin(115200);
  lcd.init();
  lcd.backlight();
  lcd.print(" Tiempo ");
  pinMode(led, OUTPUT);
  pinMode(led2, OUTPUT);
  pinMode(p1, INPUT);
  pinMode(p2, INPUT);
  pinMode(Trigger, OUTPUT); //pin como salida
  pinMode(Echo, INPUT);  //pin como entrada
  digitalWrite(Trigger, LOW);//Inicializamos el pin con 0
  tiempo1 = millis();
  tiempo2 = millis();
  digitalWrite(led2, estadoLED2);  // LED2 encendido
  digitalWrite(led, !estadoLED2);  // LED apagado
}

void loop() {
  //  tiempo2 = millis();
  if (millis() - tiempo1 >= 1000) { //Si ha pasado 1 segundo ejecuta el IF
    tiempo1 = millis(); //Actualiza el tiempo actual
    tiempoSegundos = tiempo1 / 1000; //conversion
    Serial.print("Ha transcurrido: ");
    Serial.print(tiempoSegundos);
    Serial.println(" seg desde que se encendio el Arduino");
    Serial.println(millis());
    tiempoSegundos = tiempoSegundos / 60; //Configuracion de tiempo en minutos
    lcd.setCursor(0, 1);
    lcd.print(tiempoSegundos);
    lcd.print(" minutos");
  }

  long t; //timepo que demora en llegar el eco
  long d; //distancia en centimetros

  digitalWrite(Trigger, HIGH);
  delayMicroseconds(10);          //Enviamos un pulso de 10us
  digitalWrite(Trigger, LOW);
  t = 10000;
  //  t = pulseIn(Echo, HIGH); //obtenemos el ancho del pulso
  d = t / 59;
  /*
    if (tiempoSegundos == 60000) { //intento reiniciar en este punto; cuando llegue al minuto todas las variables se van a 0
      tiempoSegundos = 0;
      tiempo1 = 0;
      tiempo2 = 0;
    }
  */

  if (millis() - tiempo2 >= 30000) { //si millis < 30000 enciende un led y el otro lo apaga
    estadoLED2 = !estadoLED2;  // invierte el estado de LED2
    digitalWrite(led2, estadoLED2);
    digitalWrite(led, !estadoLED2);  // LED en estado contrario a LED2
    myservo.write(55);
    tiempo2 = millis();  // **** esto equivale a resetear tiempo2 ****
    //delay(5000);
  }
  /*
    if (digitalRead(p2) == HIGH  || d <= 35) { //si se presiona el pulsador          enciende el led contrario un segundo
      Serial.println("bad");             //o si el sensor detecta algo <35 cm
      myservo.write(15);
      digitalWrite(led2, estadoLED2);
      digitalWrite(led, !estadoLED2);
    //  delay(5000);
    }
    if (digitalRead(p1) == HIGH) { //si se presiona el pulsador enciende el led contrario un segundo
      Serial.println("nice");
      myservo.write(15);
      digitalWrite(led2, estadoLED2);
      digitalWrite(led, !estadoLED2);
    //  delay(5000);
    }
  */
}

Fijate en el comentario con asteriscos, digo que equivale a resetear tiempo2 porque en el instante que se hace la igualdad, justo en ese momento, la diferencia entre tiempo2 y millis() es 0 (obvio, son iguales).
Como lo que controlamos es la diferencia de tiempos, cuando la diferencia sea 30000 mseg, cambia el estado de los LED y vuelve a fijar tiempo2 al nuevo millis() para volver a contar 30 seg desde ese momento.
O sea, tiempo2 solo cambia de valor cada 30 seg no en cada pasada del loop() como lo habías planteado.
Como ves no hace falta ponerlo en 0 porque lo que controlamos es la diferencia entre valores.

Ahora explica bien qué hacen los pulsadores

1 Like

A parte de lo que @MaximoEsfuerzo te comenta, te doy un consejo sobre programación en general: Huye de ese tipo de expresiones que has puesto antes.
Usa mejor del una definición tal que así if (tiempoSegundos>=60000) { dado que es más limpio y menos dado a errores futuros.

Gracias @MaximoEsfuerzo en ocasiones de necesita un tiron de orejas, y perdona si quiza suene como muy tonto y redundante en ocasiones, me agrada su idea es mas limpia y ocupa menos codigo.
Ya lo probe hasta aqui pero, solo que solo enciende led1, no inicia encendido led2.
No se si quiza sea por este cambio:

estadoLED2 = !estadoLED2;

Donde de alguna manera se confunda o algo similar, le adjunto el link de tinkercad donde hice la prueba con el circuito digital para ir de la mano, no se si le agrade un poco eso
circuito

Y respecto a los botones, los leds estaran haciendo su funcion cada 30 segundos pero digamos que dentro de ese tiempo esta encendido led2 pero quiero encender led1, entonces con el pulsador1 apaga led2 para encender led1 digamos durante 5 segundos solamente, luego de esos 5 segundos regresa a donde se quedo (led2 encendido y led1 apagado), lo mismo para el pulsador2. Eso como lo tengo en el programa digamos "base" si lo hace, no se si vea algun error en la sintaxis de los if de los botones

Moderador:
He cerrado una publicación similar en esta sección
En mayo 29 te cerre una publicación por no atender a los pedidos del moderador.
Ahora doble posteas el mismo hilo.
@joza101420 que parte no se comprende de que no debes doble postear?
Ultima advertencia!!

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