LED RGB y buzzer mediante Serial

Buenas días, este es mi segundo post, soy nuevo en esto, y me gustaría que alguien me pudiera ayudar.
Este proyecto trata sobre encender un buzzer ingresando la frecuencia y duración por Serial, y de esta misma manera, se encenderá las luces Roja, Verde o Azul dependiendo la frecuencia seleccionada para el buzzer.
Añado imagen del ejemplo:
foro arduino

Mi problema es que no importa que valor ingrese para la frecuencia, siempre se enciende la luz Verde :c. y también a veces tengo que ingresar el mismo valor como 4 veces para que arduino interactúe.
Aquí mi código:

//Declaro tres variables booleanas para controlar si está encendido el rojo
//(re),el verde(ve), y el azul(ae)

boolean re;
boolean ve;
boolean ae;
int azul = 11;
int verde = 12;
int rojo = 13;
const int zumbador = 2;

String msg = "Favor de insertar la frecuencia y duración del buzzer \n VERDE ( 1 <= frecuencia <= 21845) \n AZUL ( 21845 < frecuencia <= 43690) \n ROJO ( 43690 < frecuencia <= 65535)";

void setup() {
  //declaro los pines como salidas
  pinMode(rojo, OUTPUT);
  pinMode(verde, OUTPUT);
  pinMode(azul, OUTPUT);
  pinMode(zumbador, OUTPUT);

  //Inicializao el puerto serie
  Serial.begin(9600);
  
  //Apago los tres led
  digitalWrite(rojo, HIGH);
  digitalWrite(verde, HIGH);
  digitalWrite(azul, HIGH);
  //Indico a las booleanas que los tres led están apagados
  re = false;
  ve = false;
  ae = false;
  Serial.print(msg);
}
void loop() {
  //Leo el puerto serie
  
  char valor = Serial.read();
  int frec = Serial.read();
  //Esta sentencia considera tres casos: valor vale ‘R’, ‘G’ o ‘B’, actuando
  //en consecuencia

  //Verde
  if (frec >= 1 && frec <= 21845) {
    if (ve == true) {
      digitalWrite(verde, LOW);
      ve = false;
      
      //El verde estaba encendido; apago
      
      tone(zumbador, frec);
      delay(500);
      
    } else {
      //El verde estaba apagado; enciendo
      digitalWrite(verde, HIGH);
      noTone(zumbador);
      delay(500);
      ve = true;
    }
    }
  

  //Azul
  if (frec > 21845 && frec <= 43690) {
    if (ae == true) {
      //El azul estaba encendido; apago
      digitalWrite(azul, LOW);
      tone(zumbador, frec);
      delay(500);
      ae = false;
    } else {
      //El azul estaba apagado; enciendo
      digitalWrite(azul, HIGH);
      noTone(zumbador);
      delay(500);
      ae = true;
    }
  }

  //Rojo
  if (frec > 43690 && frec <= 65535) {
    if (re == true) {
      //El rojo estaba encendido; apago
      digitalWrite(rojo, LOW);
      tone(zumbador, valor);
      delay(500);
      re = false;
    } else {
      //El rojo estaba apagado; enciendo
      digitalWrite(rojo, HIGH);
      noTone(zumbador);
      delay(500);
      re = true;
    }
  }
}

Espero alguien me pueda ayudar, gracias y saludos.

Te digo los dos primeros problemas que veo sin profundizar demasiado.
Lees el puerto serie sin verificar previamente si hay datos para leer. Para eso se usa la función available().
Intentas cargar la frecuencia con un simple read() siendo que lo que vas a obtener es el código ASCII de un caracter. Por lo tanto estás intentando obtener la frecuencia de manera errónea.

Te pongo un ejemplo.
Supongamos que ingresas "R950"
Si tienes suerte y el puerto serie lo lees justo en el momento adecuado (porque no verificas si hay datos)
En la primera pasada del loop leerías solo los 2 primeros caracteres recibidos ("R9") por lo que

valor = 'R'
frecuencia = 57

porque 57 es el código ASCII de "9"

En la siguiente pasada del loop leerías los otros 2 caracteres ("50") entonces

valor = '5'
frecuencia = 48

porque 48 es... obvio, el código ASCII de "0"

Busca cómo leer cadenas desde serial y convertirlas a enteros u otro tipo numérico.

Saludos

Oohhh, siii con razón cuando ingresaba un número alto, de repente se detenía y no sonaba toda la frecuencia, pero si ingreso valores chicos si funciona bien.
Muchas gracias, ando en el trabajo, ya que salga buscaré como me dices y de ahí te consulto si me surgen mas dudas, gracias!!!

No hay por qué.

Saludos

No se si borraste los posts porque lo resolviste o por error. Igual te respondo.

Usa unsigned int, o bien long en la definición de frecuencia, tu problema es que la difiniste como int por lo que solo almacena valores entre -32768 y 32,767, inclusive.

Saludos

Hola gatul
Si lo borre por que justo cuando te comente lo de arriba, rápido encontré la solución, y lo borre para que no fuera necesario responderme

Ahora solo me resta como hacerle para que al mandarle 2 valores separados por una coma, los lea y funcione el circuito. He visto foros sobre implementar el parseInt() pero intento y no me funciona mucho.

Por ejemplo en mi caso, por serial mandaré supongamos "2,200", que el 2 es la frecuencia del buzzer, y el 200 es la duración en ms del buzzer, pero no lo logro implementar. Seguiré buscando por otras partes, y si lo encuentro te aviso.
Muchas gracias y saludos.

Aunque lo que pregunas esta respondido en el foro, vamos de nuevo.
La Clase String tiene todo tipo de procedimientos y funciones. Una de ellas justamente busca el caracter que deseas.

String indexOf() busca la apareción de un caracter en el String.
The String object indexOf() method gives you the ability to search for the first instance of a particular character value in a String. You can also look for the first instance of the character after a given offset. The lastIndexOf() method lets you do the same things from the end of a String.

String stringOne = "<HTML><HEAD><BODY>";
int firstClosingBracket = stringOne.indexOf('>');

Como dice el ejemplo el primer > esta en 5 contando el primero como 0 y de ahi en adelante.

Asi que en tu caso solo busca por ',' y luego sabras que desde 0 hasta ahi tienes el primer numero y desde ahi en adelante el segundo. No es exactamente lo que digo, a alguno le deberás quitar 1 o sumar 1.

1 Like

Si busque mucho en demasiados foros, hasta en inglés, pero como soy nuevo en esto no entiendo mucho, pero poco a poco empiezo a comprender un poco más, disculpen las molestias la verdad.
Muchísimas gracias Surbye! Mañana intentaré como me va con esa ayuda que me diste, gracias!

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