Calificación:
  • 0 voto(s) - 0 Media
  • 1
  • 2
  • 3
  • 4
  • 5
Leer Puerto Serie Progresivamente
#1
Buenos Dias,

Estaba escribiendo una funcion, para que me fuera leyendo el puerto serie progresivamente, os dejo el asunto:

Código:
void configuracion(){
  Serial.println("Introducir Hora");
  while(Serial.available())
  Serial.read();
  while (Serial.available() <= 0) {
    hora = Serial.read();
  }
  lcd.clear();
  lcd.print("Hora: ");
  lcd.print(hora);
  delay(5000);
}

La idea seria ir metiendo una hora, primero las horas, luego minutos y luego segundos. Limpio el buffer del puerto serie, y me meto en un while, que mientas no se reciba nada del puerto serie, no salga. Pues nada, de algun modo recibe cosas, y no se queda en el bucle esperando a que metas la hora....., el resultado es que se salta el bucle, y me devuelve un -1, es decir, como si no hubiera leido nada, pero la cuestion es, porque no se queda trincado en el bucle hasta que se escribe algo?


Alguna sugerencia?

Un Saludo y Gracias
Citar
#2
Hola Triggerr, según parece esa función la ejecutas en "Configuración", por lo tanto ¿Qué pasa si al llegar al primer bucle realmente NO hay datos en el puerto serie aún? Pues que no se para en ese bucle y sigue.

Es decir, si estás ejecutando una configuración, lo que debieras hacer es ESPERAR hasta que haya datos por el puerto serie y una vez los haya, ejecutar ese bucle.

¿entiendes lo que quiero decir?
Citar
#3
Además, en el siguiente bucle le estás diciendo que se quede leyendo del puerto serie mientras NO HAYA datos disponibles!! Osea, Serial.available() te devuelve el número de bytes disponibles y si le dices que se quede ahí mientras Serial.available sea menor o igual que 0, es decir, mientras no haya datos, difícilmente te va a guardar en la variable hora los datos leídos, puesto que no existen tales datos.
Citar
#4
Lo ideal sería que lidiaras con interrupciones y una vez que esta se produzca, leer los datos del puerto serie. Si en lugar de lidiar con interrupciones prefieres hacerlo dentro de un bucle "general", podrías hacer algo como esto:

void loop()
{
...
... aquí código realizando X tarea
...

// Ahora comprobamos si hay datos en el buffer de entrada del puerto serie
if (Serial.available())
{
int byteLeido = Serial.read();
... haces lo que necesites con el byte leído
}

...
... más código x
...
}

y por último, si realmente prefieres un bucle BLOCANTE, osea que detenga el flujo de ejecución del software hasta que tengas datos por el puerto serie, entonces deberás usar algo como esto:

...
while (Serial.available() <= 0); // Bucle cerrado a la espera de que lleguen datos al puerto serie (observa el punto y coma del final de línea)

// ahora leemos todos los bytes disponibles
while (Serial.available() {
int byteLeido = Serial.read();
... aquí haces lo que necesites con el byte leído
}
...

Esta última opción a mi personalmente no me gusta porque está consumiendo recursos innecesariamente, pero esto ya dependerá de la aplicación que pretendas desarrollar.

Un saludo
Citar
#5
Buenas Mak,

Pues la aplicacion es sencilla, es un pequeño monitor para valores del coche. Sin botones ni nada, solo una pantalla. Entonces para poner la hora y alguna cosilla mas, los primeros 5 segundos pregunta por puerto serie, que si pulsas "y", entra en configuracion, entonces entrarias a meter la hora. Por lo que entra, y pregunta por la hora, donde debe esperar a que metas un valor (Entre 0-24) y luego pasar a minutos...y asi....

Por eso necesito que se mantenga en bucle a la espera hasta introducir las horas.

Interrupciones en este aspecto con arduino y para mi aplicacion no me hace falta, porque estas centrado en meter las horas y no necesitas nada mas, osea es igual que este ahi el bucle....

El primer BUCLE del anterior codigo lo que hace es limpiar el buffer del puerto, por si hay algo que no se salga del anterior, limpiarlo vamos.

He conseguido ya hacer que funcione, me lee bien los caracteres que le introduzco, pero tengo que hacer mas pruebas, se me hace una lata tener que meter algun delay asi "random" para que funcione en condiciones la verdad.

El DO/WHILE, lo que hace es vaciar el buffer, una vez vacio, entra en el while, hasta que sea mayor que 0, es decir, que hayas mandado ya la hora, una vez entra guarda todos los valores recibidos en hora[] que es un array, y por ahora parece que me los pilla bien...

Código:
void configuracion(){
  Serial.println("Introducir Hora");
  do {
    Serial.read();
    lcd.print("1");
    delay(1);
  } while(Serial.available() != 0);
  while (Serial.available() <= 0) {
    if (Serial.available() > 0){
      for (int i = 0 ; i <= Serial.available() ; i++){
    delay(5);
    hora[i] = Serial.read();
  }
  }
}
Citar
#6
Bueno, imagino que este último código es de pruebas ¿no?

Es que sigues teniendo algún que otro fallo.

Fijate en el segundo bucle. El while(Serial.available() <=0) es decir, mientras no haya datos en el puerto serie !!

Ya te digo que ese bucle no puede ir así...

debes hacer algo más como esto:

Código:
.. aquí tu bucle de "limpieza"

// Bucle de espera hasta que haya datos en el puerto serie

while (Serial.available() <= 0);

// y ahora el bucle de lectura

int i = 0;
while (Serial.available()) {
    hora[i] = Serial.read();
    i = i + 1;
    // ... delay() si procede
}

// O este último si prefieres seguir usando el FOR

for (i = 0; i < Serial.available(); i++) {
    hora[i] = Serial.read();
    // ... delay() si procede
}

Sin embargo, tu estás metiendo la lectura de los datos DENTRO del propio bucle de espera! por lo tanto, se entiende que si el bucle espera mientras no haya datos, difícilmente vas a poder leer ningún dato desde dentro de ese bucle.

¡ Cuidado con la condición del FOR ! Menor y no menor o igual, ten en cuenta que empiezas con el índice en '0', por lo tanto si hay 12 bytes disponibles y comienzas desde el '0', el valor de la variable local 'i' irá desde '0' hasta '11', es decir, un total de 12 bytes. Sin embargo, si pones tu condición de menor-o-igual a Serial.available(), vas a leer 13 bytes... desde 0 hasta 12.
Citar
#7
Por cierto, que si aún así quieres utilizar tu condición del for, osea i <= Serial.available() entonces tendrás que cambiar todo el FOR de la siguiente manera:

Código:
for (i = 1; i <= Serial.available(); i++) {
    hora[i-1] = Serial.read();
    // ... delay() si procede
}

Es decir, si te fijas, en esta ocasión lo que he puesto es el índice desde 1 hasta Serial.available(), que si como en el ejemplo anterior fuesen 12 los bytes disponibles en el buffer, este bucle FOR va a leer desde el valor 1 hasta el 12. Pero fíjate, que en este caso tendrás que restar uno al índice para acceder al array de horas, de lo contrario estarías comenzando por el índice '1' en lugar del '0' y si no hubieras dimensionado bien ese array tendrías errores de IOR (Index out of range), con el consiguiente riesgo de sobreescritura de pila, variables locales, etc. según el caso.
Citar
#8
Buenas Noches MAK,

Estas en lo cierto, no tiene sentido meter la lectura en el While, como metes todos los caracteres de golpe en el buffer, quiero decir escribes y cargas el buffer con 3, los dos numeros y el retorno de carro, solo hay que hacer el while hasta que esten disponibles, y luego ya leer los tres, ya lo he pillado el asunto Gran sonrisa ya va perfecto.

Sobre los indices, era de prueba, los tengo que ajustar cuando sea definitivo.

Si que puede dar la lata si cuando desbordas los tamaños de las variables
Citar
#9
Guiño Me alegro!

¡Un saludo compañero!
Citar


Temas similares...
Tema Autor Respuestas Vistas Último mensaje
  Comunicación serie con arduino y java hectorri 2 1,301 25-01-2014, 03:04 PM
Último mensaje: richardmike4
  Leer llavero NFC de Arduino con smartphone? igargi 13 1,457 05-01-2014, 04:46 PM
Último mensaje: AiToR51