Duda sobre while (fácil)

¡Hola! Somos tres estudiantes de diseño empezando a programas y a usar Arduino, y tenemos una duda sobre la programación de nuestro proyecto.

El trabajo consiste en hacer un semáforo con tres leds (rojo, verde y amarillo) en la placa base y sus respectivas resistencias, todos conectados a diferentes pines. El trabajo también tiene un pulsador y un zumbador, también conectados a pines.
Supuestamente, el semáforo (que es visible para los coches) tiene que estar en verde todo el rato hasta que el pulsador es pulsado (valga la redundancia), entonces con if se inicia un loop en el que se enciende el ámbar para los coches durante unos instantes y luego se enciende el rojo 30 segundos. Hasta aquí todo bien. Nuestro problema es que queremos que mientras el semáforo rojo está encendido, el zumbador haga un sonido intermitente (que sería lo que oirían los peatones). Lo hemos probado a hacer con while, haciendo que el estado del led sea una variable, y dependiendo de si está encendido o apagado que se inicie el while. Hemos conseguido que el while funcione mientras el rojo está encendido, pero no conseguimos que se apague para que el loop empiece otra vez con el semáforo en verde. Le hemos probado a poner un Delay después del loop y después un digitalWrite LOW en el pin del led rojo, pero nada, sigue infinitamente.

Este es nuestro código con las aclaraciones sobre los pines, etc.

void setup()
{
  pinMode(5, OUTPUT); // marcar como salida el led verde
  pinMode(6, OUTPUT); // marcar como salida el led ámbar
  pinMode(7, OUTPUT); // marcar como salida el led rojo
  pinMode(8, INPUT); // marcar como entrada el pulsador
  pinMode(4, OUTPUT); // marcar como salida el zumbador
}

void loop()
{
  digitalWrite (5, HIGH);
  int estado_pulsador = digitalRead (8); // declaramos una variable con el estado del pulsador
  if (estado_pulsador == HIGH) // si el pulsador es pulsado, realiza la siguiente acción
  {
  digitalWrite(5, LOW); //  se apaga el led verde para los coches
  digitalWrite(6, HIGH); // empieza el amarillo, avisando de que cambiará a rojo
  delay(3000); 
  digitalWrite(6, LOW);
  digitalWrite(7, HIGH); // se enciende el rojo
  int estado_led = digitalRead (4);
    
 	while (estado_led = 1)
  	 {
      digitalWrite(4, HIGH);
      delay (1000); 
      digitalWrite(4, LOW);
      delay (1000);
    }
    
  }
}

Sabemos que hay maneras más sencillas de hacerlo simplemente diciéndole al zumbador que suene y deje de sonar durante un segundo y repetir eso hasta llegar a los 30 segundos que pretendemos que el semáforo esté en rojo, pero la verdad es que programar esto nos está gustando y ya es por pura curiosidad de poder hacer algo guay y aprender de ello.

Si alguien pudiera ayudarnos, ¡sería genial!

Un saludo, Marta, Pablo y Sara.

Primero creo que leen mal el estado del led rojo porque está en el pin 7, el pin 4 es el zumbador.

En lo particular no usaría delay() pero dada la sencillez del código, no veo que provoque problemas.
Yo usaría un lazo for(), en lugar del while(), que cuente de 0 a 14 y dentro de éste lo que ahora está en el while(). Así tendrían los 30 segundos con led rojo encendido y zumbador sonando cada 1 segundo.

En cuanto a estado_led le pondría true al encender el led rojo y false al apagarlo, no me convence mucho leer el estado de un pin de salida (aunque en teoría es válido).
Y en el código les faltó apagar el led rojo, por cierto.

Saludos

1 Like

¡Muchísimas gracias por contestar tan rápido!
Ahora mismo lo vamos a probar.

Un saludo <3

¡Hola de nuevo! ¡Hemos probado a hacerlo con for y nos ha salido perfecto! Muchísimas gracias otra vez.

Esta es una versión que espero funcione donde uso dos máquinas de estado y millis().
También defino todas las contastantes con etiquetas para una fácil lectura e interpretación.
Aunque como bien dice @anon90500195 el ejercicio tolera el uso de delay() les aconsejo olvidarlo porque les dará mas problemas que soluciones.
Usar millis() y máquinas de estado es mas complicado al comienzo pero cuando hacen el click mental luego suerge fácil.
En Documentación y tutoriales se explica que es una máquina de estados y tmb como usar millis(). Vayan y leanlo para luego entender esto.
Espero funcione.

#define VERDE     5
#define AMBAR     6
#define ROJO      7
#define PULSADOR  8
#define ZUMBADOR  4

int estado_pulsador, estado_pulsadorAnt = 0;
int inicioAccion = 0, inicioZumbador = 0;
unsigned long inicioDelay, inicioZumbaDelay;

void zumbador() {
  switch (inicioZumbador) {
    case 0: digitalWrite(ZUMBADOR, HIGH);
            inicioZumbador = 1;
            inicioZumbaDelay = millis();
            break;
    case 1: if (millis() - inicioZumbaDelay > 1000UL) {
                digitalWrite(ZUMBADOR, LOW);
                inicioZumbador = 2; 
            }
            break;
    case 2: if (millis() - inicioZumbaDelay > 1000UL) {
                inicioZumbador = 0; 
            }
            break;
  }
}
void setup() {
  pinMode(VERDE, OUTPUT); // marcar como salida el led verde
  pinMode(AMBAR, OUTPUT); // marcar como salida el led ámbar
  pinMode(ROJO, OUTPUT); // marcar como salida el led rojo
  pinMode(PULSADOR, INPUT); // marcar como entrada el pulsador
  pinMode(ZUMBADOR, OUTPUT); // marcar como salida el zumbador
}
void loop() {
  digitalWrite (VERDE, HIGH);
  int estado_pulsador = digitalRead (PULSADOR); // declaramos una variable con el estado del pulsador
  if (estado_pulsador && !estado_pulsadorAnt) {  // si el pulsador es pulsado, realiza la siguiente acción
      inicioAccion = 0;
  }
  switch (inicioAccion) {
    case 0: digitalWrite(VERDE, LOW);   //  se apaga el led verde para los coches
            digitalWrite(AMBAR, HIGH);  // empieza el amarillo, avisando de que cambiará a rojo
            inicioAccion = 1;
            inicioDelay = millis();
            break;
    case 1: if (millis() - inicioDelay > 3000UL) {
                digitalWrite(AMBAR, LOW);
               digitalWrite(ROJO, HIGH);   // se enciende el rojo
                inicioDelay = millis();
                inicioZumbador = 0;
                inicioAccion = 2;
            }
            break;
    case 2: if (millis() - inicioDelay > 30000UL) {
                digitalWrite(ROJO, LOW);   // se apaga el led ROJO
                digitalWrite(ZUMBADOR, LOW); // me aseguro que el zumbador quede apagado.
                inicioAccion = 3;   // no repito mas hasta que se presione de nuevo el pulsador
            }
            else {  // aca hago la acción del zumbador
                  zumbador();
            }
            break;
    case 3: // se queda aca sin hacer mas nada la máquina de estados.
            break;
  }     
}

Moderador:
Qué raro esto: dos temas similares al mismo tiempo.
[Semáforo con botón peatonal (para pasar)](Semaforo con boton peatonal para pasar)

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