Rubén Beiroa Mosquera

Aprender Arduino, prototipado y programación avanzada con 100 ejercicios


Скачать книгу

de un sistema multitarea se tratase.

image image image image image

       013

      Interrupción del puerto serie

      En el caso de utilizar, por ejemplo, la comunicación serie, tenemos algo parecido a una interrupción asociada a la recepción de datos. No es exactamente una interrupción porque, si recordamos, una interrupción detiene la ejecución normal del programa y ejecuta la función asociada a la interrupción.

      En el caso de la interrupción del puerto serie, esto no sucede; lo que realmente ocurre es que el programa comprobará, cada vez que finalice el bucle void loop, si hay datos en el buffer de entrada del puerto serie y, si es así, se ejecuta una función:

      •Existen unas funciones predefinidas para este tipo de uso, que son las funciones <<serialE-vent()>>.

      •En el caso de que un Arduino tenga varios puertos, como es el Arduino Mega, cada puerto tiene su propia «interrupción», diferenciándose por la referencia del puerto serialEvent1(), serialE-vent2()…

      •En el siguiente caso image, podemos comprobar el funcionamiento de la «interrupción» del puerto serie.

      •Esta función viene a sustituir el if (serial.available()) image, consiguiendo así simplificar el programa, pero con el inconveniente de que solo se comprueba el puerto serie al finalizar el bucle void loop().

      •Esto último podemos probarlo con dos simples casos:

      •En el primero image se introduce un delay de cinco segundos en el bucle void loop para, así, comprobar que, aunque enviemos un mensaje por el monitor serie, mientras no finalice la temporización, no se comprobará si hay datos para posteriormente devolverlos.

      •En el segundo image, programamos un bucle infinito dentro del void loop, haciendo así que nunca se llegue a finalizar este, con lo que, por muchos mensajes que enviemos, ninguno de ellos será devuelto.

      Visto todo esto, la conclusión sería que podemos programar una función para la recepción de datos por el puerto serie que nos permite liberar código del bucle principal.

      Pero, en un Arduino, no hay únicamente un tipo de comunicación; en los siguientes capítulos trabajaremos con las comunicaciones I2C y SPI y aí veremos que también tienen funciones para la recepción de datos.

      Antes de estudiar estas comunicaciones, profundizaremos en el lenguaje de programación de la comunicación serie. Son muchos los módulos que utilizan esta comunicación; para establecer una comunicación eficiente, será imprescindible un buen dominio del lenguaje de programación.

      Aunque los módulos ya adaptados para Arduino seguro que tienen sus propias librerías con las que conseguimos establecer de forma fácil una comunicación, existen muchos otros dispositivos que no tendrán una librería para Arduino y es ahí donde será necesario conocer ciertas peculiaridades de la comunicación serie.

image image image image

       014

      Comunicación serie Serial.flush, Serial.availableForWrite

      Serial.flush():

      Al usar «print», «println» o «write», la transmisión de datos se realiza de forma asíncrona. Esto quiere decir que se ejecuta la siguiente instrucción sin asegurarse de que se empiece el envío de datos.

      Esta cuestión se soluciona si, después de cualquiera de las tres instrucciones anteriores (print, println o write), escribimos <<Serial.flush()>>. Esta instrucción no devuelve nada, pero bloquea el programa hasta que el buffer de salida se haya vaciado, lo que significa que se han enviado todos los datos:

      1.Para comprobar esto, probamos a enviar un mensaje y capturar el tiempo que tarda en ejecutarse el programa.

      2.El tiempo que tardaría el programa en escribir el mensaje en el buffer de salida serían de 220 microsegundos image, pero solo se han escrito en el buffer; no se han enviado.

      3.Ahora haremos lo mismo pero añadiendo la instrucción <<Serial.flush()>>.

      4.En este caso, el tiempo es notablemente superior, ya que se fuerza al programa a detenerse hasta que se haya enviado toda la información image.

      Serial.availableForWrite():

      Esta instrucción devuelve el número de bytes libres en el buffer de salida; esto nos va a permitir recalcar lo que hemos visto en el punto anterior: el buffer dispone de 63 posiciones y, al ejecutar las instrucciones <<Serial.print>>, <<println>> o <<write>>, lo que se hace es escribir datos en el buffer, pero ello no significa que se hayan enviado, cosa que sí conseguimos con <<Serial.flush();>>:

      1.Volvemos a enviar el mensaje anterior, pero de esta vez sin añadir <<Serial.flush()>>.

      2.Si, a continuación de la instrucción <<Serial.println()>>, comprobamos el número de caracteres libres que hay en el buffer de salida, nos indica que 33 image y esto es porque el mensaje que enviamos está formado por 30 caracteres, por lo que, de los 63 que puede memorizar el buffer, 30 están ocupados y 33 están libres.

      3.Ahora hagamos lo mismo pero asegurándonos con la instrucciones <<Serial.flush()>> de que se vacía el buffer de salida.

      4.En este caso, nos devuelve el valor 63, por lo que el buffer está completamente vacío, lo que significa que se ha enviado todo el mensaje image.

      Con todo esto, acabamos de analizar en profundidad el proceso de transmisión de datos por parte de un Arduino utilizando la comunicación serie. Antes de continuar con el siguiente capítulo, cabe mencionar que, en caso de querer enviar un mensaje de más de 63 caracteres, pongamos, por ejemplo, que esté formado por 90, tanto la instrucción <<Serial.print()>> como <<Serial.println()>> sí que esperan a poder escribir los 90 caracteres en el buffer.

      Esto implicaría que se escribirán los 63 primeros caracteres del mensaje y, según vayan quedando espacios libres porque el buffer los transmite, la instrucción va soltando los caracteres pendientes, así hasta que suelte los 27 que le quedan pendientes y, en ese caso si, que continúa con la ejecución del programa, quedando pendientes de envío en