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:
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.
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 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.
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.
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!