[SOLUCIONADO] Modificar Valor Puerto Serie.

Buenas a todos. :slight_smile:

Tengo un pequeño problemilla, a ver si me podéis echar una mano.

Dentro de un bucle for utilizo while (Serial.available() !=3 ){} para que el Arduino espere una entrada de tres caracteres antes de enviar él su información. El problema es que la primera vez que se ejecuta el for espera esos tres caracteres pero la siguiente ya no.

Supongo que en las siguientes iteraciones del bucle for la condición del while es cierta, por eso el programa no se para.

No sé, seguro que es una tontería pero no doy con ella. Os dejo el código a ver si me podéis ayudar.

       for (int i = 1; i<= 100; i++){
         V_Previo = analogRead(A0);
         Datos = V_Previo * (5.0 / 1023.0);
         dtostrf(Datos, 5 , 3 , Se_Envia);        
         Serial.print(Se_Envia);
         delay(15);
         
         while (Serial.available() != 3 ) {
         }
       }

Gracias. :slight_smile:

El problema es que verificas si hay algo en el puerto serial pero nunca lo extraes, entonces en la segunda vez que pase el programa por esa parte seguirán los tres caracteres enviados aciendo que se cumpla la condicion

if(Serial.available()>2){
	for(int i;i < 3;i++){
		int a;
		a = Serial.read();
	}
}

Ese seria mi código.
Hay lo que estoy haciendo es condicionar la entrada a tres caracteres recibidos y al entrar los leo y guardo en una variable que no me servirá para nada ya que esta solo para borrar lo que hay en el buffer serial.
Ahora lo que no se es que si solo pongo esto

Serial.read();

Se pueda vaciar el serial aunque no se almacene y el programa en cuestión quedaría así

if(Serial.available()>2){
	for(int i;i < 3;i++){
		Serial.read();
	}
}

Si no es así avicien para aprender.
Espero y te sirva esto.

Gracias por el comentario.

No aparece en el código porque la lectura la hago desde un programa externo, pero sí que se leen los valores.

Un saludo, Enrique.

Enryke: No aparece en el código porque la lectura la hago desde un programa externo, pero sí que se leen los valores.

Explícate bien esta parte, porque así no tengo idea si "leer externamente" vacía el búfer del serial o qué...

He respondido a lo que me he imaginado y si se esta leyendo los datos en puerto serial, seria bueno saber cuantos caracteres hay justo antes del while para saber que esta sucediendo asi como lo dice Lucario448

Buenas,

Gracias a los dos por contestar.

El programa externo es básicamente Visual Basic y vacía el buffer. También he probado a cambiar los valores del buffer desde el propio Arduino (escribir valores para leerlos después) pero el problema persiste.

Lo que necesito es escribir un valor para que lo lea VB y esperar una respuesta del programa en VB para coordinar la comunicación.

El problema es que cuando trabajo con varios valores se leen y escriben descoordinadamente a pesar de que la comunicación está establecida a los mismos baudios.

Un saludo, Enrique.

Como garantizas que el buffer se vacía en el momento correcto.
Que función usas para leer el buffer.
Ahora a jugar un poco:

Por lo que veo Arduino envía “Se_Envia” a visual basic y entra en el bucle while.
Para salir de ese bucle únicamente tienes que mandar 3 caracteres. Si mandas mas no sale y si mandas menos de 3 caracteres tampoco sale.

Pero yo veo

for (int i = 1; i<= 100; i++){
         V_Previo = analogRead(A0);
         Datos = V_Previo * (5.0 / 1023.0);
         dtostrf(Datos, 5 , 3 , Se_Envia);        
         Serial.print(Se_Envia);

Y luego el while, para esto yo asumo que

Serial.print(Se_Envia);

es quien se comunica con Visual Basic

entonces mientras Visual Basic no envié tres caracteres no sale de for
y una vez enviado los tres caracteres for se va como loko enviando datos(disculparan pero ya es como mi firma escribir loko asi)
Eso es lo que te entendi.

Tienes que garantizar que en la siguiente iteracion el buffer esta vacio porque while solo sale si están los tres caracteres.

Como yo lo garantizaría.
Antes de tu while y monitoreando con tu propio programa y este también se pare en su ejecución.

Serial.printl(Serial.available());
delay(99999);

y asi saber si esta pasando lo que crees que pasa dentro del programa(sin ofender)…

Enryke: El programa externo es básicamente Visual Basic y vacía el buffer.

Un momento. Me estas queriendo decir que ese programa puede acceder a la memoria (RAM) del Arduino y modificarla vía puerto serial?

No sé tú, pero eso me das a entender con eso de "y vacía el buffer".

Estamos hablando del búfer RX del Arduino, no el del programa en Visual Basic.

Un búfer es una estructura de datos "estilo array" FIFO (primero que entra, primero que sale). Cada byte que entra, ocupa un espacio e incrementa el contador para available. Cada lectura descarta un byte del búfer, desocupa un espacio y desincrementa el contador para available (pero nunca será menor que cero).

El búfer se llena mediante una interrupción (ocurre implícitamente y en cualquier parte del programa principal), y se vacía con el llamado a cualquier función de la clase Serial que lleve la palabra "read" o "flush".

En resumen: cada parpadeo de RX incrementa el resultado de available (máximo 64); cada read lo desincrementa (mínimo 0).

No es posible predecir sólo con código, el resultado de available si los incrementos son desencadenados por medios físicos (pulsos de voltaje en RX); pero sí los desincrementos. Los incrementos sólo es posible predecirlos si se conoce la cantidad de bytes/caracteres que se recibe, y con cuánta frecuencia.

Si se conocieran ambas cosas con certeza, entonces se pueden realizar las sumas y restas necesarias para poder llegar a la solución a tu problema.

Hola Enryke. No sé si soy yo que estoy un poco espeso; pero creo que nadie termina de comprender el problema que planteas. Cuando en las normas del foro se indica que se ponga toda la información posible no es porque sí. En este caso el no ver todo tu programa (especialmente la parte donde lees los datos) ni lo que envía el programa en Visual Basic, hace que estemos dando palos de ciego. Con la poca información que proporcionas, lo único que se me ocurre es que estás recibiendo datos de forma distinta a la que crees. Por ejemplo puede ser que te estén llegando finales de línea y no cuentes con ellos e interfieran en los tres bytes que quieres recibir. Si no has sabido encontrar tu propio error, probablemente no esté donde tú piensas. Lo mejor será que amplíes información.

Gracias a todos por contestar.

Lucario ha dado con uno de los problemas que tenía. Estaba un poco espeso y lo que estaba modificando era la parte de Visual Basic.

Lo del delay() tan grande me parece un poco locura, ¿no, StringCGE?

Respecto a lo que comentas, noter. Lamento no haberme expresado de forma suficientemente clara. Si necesitáis más datos os paso la librería de VB que estoy utilizando: http://people.uwplatt.edu/~evensenh/Hal_Evensens_Homepage/VBA_Communication.html

Para lo que dices de posibles caracteres que no esté contemplando, probé también modificando las cadenas con .trim(); y nada de nada :S .

Es el primer link de esa web. (Está en inglés). No la pasé antes porque no sabía muy bien como hacerlo y porque, en principio, el problema está solo en limpiar el buffer de Arduino.

En cuanto a lo de la función flush, fue mi primera opción... pero me dio problemas.

Voy a seguir trabajando un poco con todo esto, aprovechando la aclaración de Lucario (muchas gracias :) ). Cuando tenga algo claro (o si veo que me quedo muy estancado) os comento. Espero que más claro que antes.

Todo esto de mezclar lenguajes de programación me tiene un poco loco XD.

Gracias a todos de nuevo.

Buenas de nuevo.

Ya está solucionado. Era tan fácil como limpiar el Buffer de Arduino (cosa que pensaba que estaba haciendo pero no XD ). Sería que ayer llevaba todo el día programando y ya tenía la cabeza loca.

Muchas gracias a todos por el apoyo. La clave para caer en mi error estuvo en la explicación de Lucario (a veces necesitas que te digan algo que ya sabes para entenderlo).

Voy a seguir trabajando y cuando lo tenga todo bonito y bien organizado os lo posteo.

Muchas gracias a todos. :slight_smile:

Ponle solucionado. Edita tu post inicial y agrega [SOLUCIONADO]

No doy con el sitio para cambiarle el título al post, surbyte. :S Si me das alguna pista lo cambio en un momento. :)

Para los que me habéis ayudado y los que se pasen a leer por aquí, os dejo el resultado como os prometí :)

Han sido muchas las modificaciones, pero al final esta es la opción por la que me he decantado. :)

http://www.educachip.com/enviar-datos-arduino-a-excel-tiempo-real/

Muchas gracias a todos.

Enryke: Ya está solucionado. Era tan fácil como limpiar el Buffer de Arduino

Funciona si el recibimiento ocurriera en intervalos no tan cortos.

Para flujos de datos constantes (que nunca se detienen), vaciar el búfer no es una opción (provoca pérdida de información en aplicaciones de tiempo real, por ejemplo). En este caso sí es necesario darle un formato a la información, a esto se le llama "paquete" o "frame". Usualmente se componen así:

marcador del inicio del paquete (1 o 2 bytes) - información (longitud arbitraria) - marcador del fin del paquete (opcional si se puede deducir la longitud de la información)

En flujos continuos, esto sirve para saber cuando un dato empieza, y cuando acaba.

Si el tiempo importara (y/o hay riesgo de un eventual llenado del búfer), entonces ahí lo mejor sería que los datos sean recibidos en forma binaria y no como texto. Recibir texto implica tener que hacer una conversión (conocida como "parse"); en cambio, en forma binaria el dato se puede usar inmediatamente (además de que se "comprime", ocupando menos espacio en el búfer a la hora de recibirlo).

Buenas de nuevo,

El problema está en la gestión de los bits de control de flujo de Arduino. No tengo acceso a ellos como los tendría en RS-232. Si hubiese sido capaz de hacer eso todo habría sido más simple, Lucario. :)

El caso es que me puse a buscar sobre eso y tampoco creas que encontré gran cosa. Me estaba volviendo un poco loco.

Un saludo.

El problema está en la gestión de los bits de control de flujo de Arduino. No tengo acceso a ellos como los tendría en RS-232. Si hubiese sido capaz de hacer eso todo habría sido más simple, Lucario. :)

A que te refieres con ésto?

Buenas,

A las señales típicas que te indican que un dispositivo reconoce al otro, que está listo para enviar, que el otro está listo para recibir y demás.

Desde las instrucciones de la librería serial no sé gestionar eso. Tampoco he mirado con profundidad la posibilidad de hacerlo directamente en AVR, la verdad. Lo mismo por ahí es más fácil tirar.

En cualquier caso, tampoco es que esté muy especializado en este tipo de comunicaciones. Supongo que me tocará mirarlo todo con más tiempo. XD

Un saludo, Enrique.

Pero eso ya no se usa (en líneas generales), yo recuerdo trabajar con micros mas chicos que éstos y en Assembler implementaban todas las señales.
Hacerlo con Arduino no es problema.
Quieres crear funciones RTC, CTS, DSR y DTR. No hay problema. Pines tienes pero tendras que reescribir todo a nivel mas bajo.
Busca en AVR porque eso esta hecho.
Acá lo que te acabo de mencionar http://www.avrfreaks.net/forum/usings-cts-and-rts-atmega-microcontrollers
y alguna ayuda mas
http://www.avrfreaks.net/forum/handling-rts-cts-uart

No había dado yo con eso. Muchas gracias surbyte.

Le voy a dar buen uso a eso en mis proyectos. :)

Cuando me ponga y me quede algo funcional y bonito os lo comparto. :)

Acá hay dos niveles. Imagina un nivel MACRO que es Arduino con instrucciones que tienen mucho código detras y por eso no son óptimas y un nivel micro que es AVR. Cuando requieres algo como lo que pides, ve a la vuente. Tiene muchos pero muchos aÑos de experirencia un foro como AVRFreaks donde se ha hecho de todo. Buscá ahi y econtrarás tu respuesta.