Buzzer suene 1 vez y led se mantenga encendido

La siguiente programación trata de lo siguiente:

El sensor ultrasónico detectará las distancias y ejecutará las instrucciones dentro de cada "IF".
Dentro del primer "IF" (d>=15 && d<=20), se tiene un contador para que al detectar una misma distancia por 10 segundos, recién ejecute la instrucción de encender la luz roja y hacer sonar el buzzer. El problema que tengo, es que, como es una función en bucle, el buzzer al apagarse, vuelve a sonar después del periodo de tiempo. Necesito que solo suene la primera vez y que no vuelva a sonar más, pero que el LED rojo se mantenga encendido hasta que la distancia cambie (Ósea, que el sensor ultrasónico detecte otra distancia).

const int LEDPinr = 12;
const int LEDPina = 8;
const int LEDPinv = 7;
const int Trigger = A2;
const int Echo = A1;
long t;
long d;
int j = 0; 
void setup()
{
Serial.begin(9600);
pinMode(LEDPinr, OUTPUT);
pinMode(LEDPina, OUTPUT);
pinMode(LEDPinv, OUTPUT);
pinMode(Trigger,OUTPUT);
pinMode(Echo,INPUT);
digitalWrite(Trigger, LOW);
}

void loop(){
digitalWrite(Trigger, HIGH);
delayMicroseconds(10);
digitalWrite(Trigger, LOW);
t = pulseIn(Echo, HIGH);
d = t/57;
 
  if(d>=15 && d<=20){
     if (j==10){
      digitalWrite(LEDPina, LOW);
      digitalWrite(LEDPinr, HIGH);
      digitalWrite(LEDPinv, LOW);
      delay(500);
      tone(3,500);
      delay(10000);
      noTone(3);
      delay(2000);
      j=0;  
     }
   j+=1;
   delay(2000);  
  }
  if(d>=4 && d<=14){
     digitalWrite(LEDPina, HIGH);
     digitalWrite(LEDPinr, LOW);
     digitalWrite(LEDPinv, LOW);
     noTone(3);
     delay(20000);
  }
  if(d>=21 ){
     digitalWrite(LEDPina, LOW);
     digitalWrite(LEDPinr, LOW);
     digitalWrite(LEDPinv, HIGH);
     noTone(3);
     delay(500);
  }
 

Establecer una bandera para "zumbador"

if (j==10)
{
    bandera = 1;
.
.
.
    If (bandera != 1)
    {
        tone....
        .
        .
        .
    }
}

Pensé que solo querías que el timbre sonara una vez.

"si la distancia es la misma durante 10 segundos, enciende el LED y...

PRIMERA vez a través del ciclo "...entonces inmediatamente configure "buzzerflag = 1", lo que significa que el zumbador ha sonado".

OTRAS veces a través del bucle, "... si la distancia es la misma durante 10 segundos, encienda el LED y... si la bandera del zumbador = 0... haga sonar el zumbador"

Necesito que en la programación del IF(d>=15 && d<=20), el LED rojo siga prendido hasta que la distancia cambie, pero que el buzzer suene solo la primera vez hasta que esa distancia cambie, pues en el código presentado a continuación, el LED rojo si se mantiene encendido, pero el buzzer vuelve a sonar después de cierto tiempo y yo necesito que solo suene la primera vez y no suene más hasta que el sensor ultrasonico vuelva a detectar alguna distancia dentro de los intervalos presentados. (Como una especie de reinicio)

¿Cómo quedaría el código completo?

const int LEDPinr = 12;
const int LEDPina = 8;
const int LEDPinv = 7;
const int Trigger = A2;
const int Echo = A1;
long t;
long d;
int j = 0; 
void setup()
{
Serial.begin(9600);
pinMode(LEDPinr, OUTPUT);
pinMode(LEDPina, OUTPUT);
pinMode(LEDPinv, OUTPUT);
pinMode(Trigger,OUTPUT);
pinMode(Echo,INPUT);
digitalWrite(Trigger, LOW);
}

void loop(){
digitalWrite(Trigger, HIGH);
delayMicroseconds(10);
digitalWrite(Trigger, LOW);
t = pulseIn(Echo, HIGH);
d = t/57;
 
  if(d>=15 && d<=20){
     if (j==10){
      digitalWrite(LEDPina, LOW);
      digitalWrite(LEDPinr, HIGH);
      digitalWrite(LEDPinv, LOW);
      delay(500);
      tone(3,500);
      delay(10000);
      noTone(3);
      delay(2000);
      j=0;  
     }
   j+=1;
   delay(2000);  
  }
  if(d>=4 && d<=14){
     digitalWrite(LEDPina, HIGH);
     digitalWrite(LEDPinr, LOW);
     digitalWrite(LEDPinv, LOW);
     noTone(3);
     delay(20000);
  }
  if(d>=21 ){
     digitalWrite(LEDPina, LOW);
     digitalWrite(LEDPinr, LOW);
     digitalWrite(LEDPinv, HIGH);
     noTone(3);
     delay(500);
  }
}

Me equivoco o ya tienes un tema abierto sobre la misma cuestión?

Pedí la eliminación del otro tema. Creo haberme explicado mejor en este. Realmente necesito ayuda :frowning:

Ya te han hecho sugerencias @xfpd post#2, las probaste?

No he probado este código. En mi publicación anterior, "escribí una historia" para su código. Puede encontrar que "escribir una historia" lo ayudará a escribir su código final. Es posible tratar de poner ideas en código de inmediato, pero debe estar en el "estado de ánimo" correcto para que funcione. Entonces, para ayudarlo a usar sus propias ideas en su proyecto final, agregué algunas líneas de código hechas comentarios dentro de su código y las publique aquí:

// Algunas declaraciones #include<> deberían estar aquí...

const int LEDPinr = 12; // roja
const int LEDPina = 8;  // amarilla
const int LEDPinv = 7;  // verde
const int Trigger = A2;
const int Echo = A1;
long t;                 // trigger
long d;                 // delay
int j = 0;
void setup()
{
  Serial.begin(9600);
  pinMode(LEDPinr, OUTPUT);
  pinMode(LEDPina, OUTPUT);
  pinMode(LEDPinv, OUTPUT);
  pinMode(Trigger, OUTPUT);
  pinMode(Echo, INPUT);
  digitalWrite(Trigger, LOW);
}

void loop() {

  // ********************************************************************************
  bool tonoSonado = 0;            // agregue y borre esta variable local para el indicador Tono sonado
  // ********************************************************************************

  digitalWrite(Trigger, HIGH);
  delayMicroseconds(10);
  digitalWrite(Trigger, LOW);
  t = pulseIn(Echo, HIGH);
  d = t / 57;

  if (d >= 15 && d <= 20) {
    if (j == 10) {
      digitalWrite(LEDPina, LOW);
      digitalWrite(LEDPinr, HIGH);
      digitalWrite(LEDPinv, LOW);
      delay(500);

      // ********************************************************************************
      if (tonoSonado == 0) // agregue esta declaración condicional
      { //  poner la declaración entre llaves
        tone(3, 500);

        tonoSonado = 1; // configurado una bandera de Tono Sonado

        delay(10000);
        noTone(3);
      } // fin de la condición
      // ********************************************************************************
      delay(2000);
      j = 0;
    }
    j += 1;
    delay(2000);
  }
  if (d >= 4 && d <= 14) {
    digitalWrite(LEDPina, HIGH);
    digitalWrite(LEDPinr, LOW);
    digitalWrite(LEDPinv, LOW);
    // ********************************************************************************
    noTone(3);                    // si el indicador Tono sonado funciona, probablemente no sea necesario
    // ********************************************************************************
    delay(20000);
  }
  if (d >= 21 ) {
    digitalWrite(LEDPina, LOW);
    digitalWrite(LEDPinr, LOW);
    digitalWrite(LEDPinv, HIGH);
    // ********************************************************************************
    noTone(3);                    // si el indicador Tono sonado funciona, probablemente no sea necesario
    // ********************************************************************************
    delay(500);
  }
}

Probé el código que realizaste, pero el buzzer no suena.

El buzzer en teoría, su única función es avisar (sonar) solo una vez cuando el sensor ultrasónico detecta una misma distancia por 10 segundos y así, sucesivamente, las veces que sea necesario. Yo creo que aún no logro explicarme :frowning:

De todos modos, te haré un ejemplo

  1. distancia 18 cm detectada por 10 segundos
  2. enciende luz led rojo
  3. buzzer suena solo una vez para avisar que se llegó a esa distancia. no vuelve a sonar hasta que se detecte una nueva distancia dentro del rango (d>=15 && d<=20)
  4. led se mantiene rojo hasta que esa distancia cambie
  5. sensor detecta distancia 10 cm
  6. led amarillo enciende
  7. led rojo apaga
  8. distancia 20 cm detectada por 10 segundos
  9. led rojo enciende
  10. led amarillo apaga
  11. buzzer suena solo una vez para avisar que se llegó a esa distancia. no vuelve a sonar hasta que se detecte una nueva distancia dentro del rango (d>=15 && d<=20)

.
.
.
.

En teoría eso es lo que quiero lograr hacer con la programación. Como lo había dicho, en mi código inicial logré el 90% de lo que quiero hacer, pero no logro hacer que el buzzer suene solo una vez para avisar y que no vuelva a sonar hasta que nuevamente se detecte una nueva distancia dentro de ese rango por 10 segundos.

Espero haberme explicado mejor.

(Si es necesario editar bastante el código, accedo a ello)

No quiero decepcionarte pero tu código está muy lejos de hacer lo que quieres que haga.

Mientras esté en el rango 15/20 y hasta que jota llegue a 10 (lo que demora 20 segundos) no hace nada. Y cuando llega a 10 enciende un led, apaga otros 2 y hace sonar el buzzer durante 10 segundos más otros 2 segundos en silencio y sin hacer nada más por culpa de los delays.
En el rango 4/14 enciende un led, apaga otros 2 y pierde 20 segundos sin hacer nada (otra vez por culpa del delay).
Y si esta más allá de 21, enciende un led, apaga otros 2 y esta vez al menos solo pierde 1/2 segundo (si, por el delay)

Pero de lo que dices que debe hacer, poco y nada.

Lee en la sección Documentación los tutoriales sobre millis() que es lo que debes usar.

Saludos

PD: Y no escribas en mayúsculas porque equivale a gritar y gritando no resuelves nada.

El tema de los delays tienen razón de ser y lo cual no la he explicado ni la explicaré por que no tiene sentido con el problema que estoy tratando de solucionar acá. El problema que tengo es solo con esa función que necesito que haga el buzzer. Tienes alguna sugerencia?

Moderador:
Por favor, lee las Normas del foro y edita tu post#10 donde usas mayúsculas.
https://forum.arduino.cc/t/sobre-escribir-todo-en-mayusculas/308285/2
Te envío privado con detalles.

¿O sea que para vos un delay de 10 o 20 segundos no interfiere con lo que pretendes hacer?
Bien...

Saludos

Escribí esto mal

if (tonoSonado = 0)

necesita dos signos "==".

if (tonoSonado == 0)

No es la mejor programación, pero logré hacer lo que quería. Saludos!

const int LEDPinr = 12;
const int LEDPina = 8;
const int LEDPinv = 7;
const int Trigger = A2;
const int Echo = A1;
long t;
long d;
long save1;
long save2=0;
int j = 0;
void setup(){
Serial.begin(9600);
pinMode(LEDPinr, OUTPUT);
pinMode(LEDPina, OUTPUT);
pinMode(LEDPinv, OUTPUT);
pinMode(Trigger,OUTPUT);
pinMode(Echo,INPUT);
digitalWrite(Trigger, LOW);
}

void loop(){
digitalWrite(Trigger, HIGH);
delayMicroseconds(10);
digitalWrite(Trigger, LOW);
t = pulseIn(Echo, HIGH);
d = t/57;
 
  if(d>=15 && d<=20){
     if (j==10){ 
      digitalWrite(LEDPina, LOW);
      digitalWrite(LEDPinr, HIGH);
      digitalWrite(LEDPinv, LOW);
       if(save1 != save2){
        save2=save1; 
        tone(3,500);
        delay(10000);
        noTone(3);
        j=0; 
       }        
     }
   j+=1;
   delay(1000);  
  }
  
  if(d>=4 && d<=14){
     digitalWrite(LEDPina, HIGH);
     digitalWrite(LEDPinr, LOW);
     digitalWrite(LEDPinv, LOW);
     noTone(3);
     delay(20000);
     j=0;
     save1=d;
     save2=0;
  }
  
  if(d>=21 ){
     digitalWrite(LEDPina, LOW);
     digitalWrite(LEDPinr, LOW);
     digitalWrite(LEDPinv, HIGH);
     noTone(3);
     j=0;
     save1=d;
     save2=0;
  }
}

Por este camino vas mal programando. Puede que este caso funcione y claramente no es muy complejo , pero te diré algo x 10 o 20 segundos tu dispositivo no hace nada y pasa por alto todo obstáculo que se cruce.
Imagina una alarma o un robot que se esta moviendo en 10 segundos cuantos cm recorres? Bueno ya chocó contra todo lo que te imagines.
Consejo: Ve a Documentación y aprende ya a usar millis() y programar de otro modo.