24/01/2022
Cuando trabajamos con proyectos Arduino que requieren interactuar con múltiples dispositivos serie, como módulos Bluetooth, GPS, sensores o pantallas, a menudo nos encontramos con una limitación fundamental: la mayoría de las placas Arduino solo disponen de un puerto serie hardware dedicado (UART), asociado a los pines digitales 0 (RX) y 1 (TX). Este puerto es esencial, ya que también se utiliza para la comunicación con el ordenador a través del puerto USB, lo que puede complicar la depuración o el uso simultáneo de otros periféricos. Aquí es donde la librería SoftwareSerial se convierte en una herramienta indispensable. Diseñada para emular la funcionalidad de un puerto serie utilizando pines digitales estándar, SoftwareSerial abre un mundo de posibilidades al permitirnos establecer comunicaciones serie adicionales en nuestra placa.

- ¿Qué es SoftwareSerial y Por Qué lo Necesitas?
- Funcionamiento Interno: La Magia de la Emulación
- Limitaciones Importantes a Considerar
- Funciones Clave de la Librería SoftwareSerial
- Comparación: Hardware Serial vs. SoftwareSerial vs. AltSoftSerial
- Consideraciones Adicionales y Mejores Prácticas
- Ejemplos de Aplicación de SoftwareSerial
- Preguntas Frecuentes sobre SoftwareSerial Arduino
- ¿Puedo usar SoftwareSerial en cualquier pin digital?
- ¿Cuántos puertos SoftwareSerial puedo tener?
- ¿Es SoftwareSerial tan rápido como el puerto serie hardware?
- ¿Cuándo debo usar SoftwareSerial en lugar del puerto serie hardware?
- ¿Qué es AltSoftSerial y cuándo debo considerarlo?
- ¿Qué significa inverse_logic en SoftwareSerial?
- ¿Cuál es el tamaño del búfer de recepción de SoftwareSerial?
¿Qué es SoftwareSerial y Por Qué lo Necesitas?
El soporte serie integrado en el hardware Arduino, gestionado por un componente llamado UART, permite que el microcontrolador ATmega reciba y transmita datos serie de manera eficiente, incluso mientras ejecuta otras tareas, gracias a su búfer de memoria de 64 bytes. Esta es una solución robusta y de alto rendimiento para una comunicación serie fiable.
Sin embargo, la realidad de muchos proyectos es que un único puerto serie no es suficiente. Imagina que necesitas conectar un módulo GPS para obtener coordenadas y, al mismo tiempo, un módulo GSM para enviar mensajes de texto, todo mientras mantienes un canal de depuración con tu ordenador. Con solo el puerto serie hardware, esto sería un desafío. SoftwareSerial fue desarrollada precisamente para superar esta limitación. Permite a los desarrolladores crear puertos serie adicionales en prácticamente cualquier pin digital de Arduino, replicando la funcionalidad del hardware a través de software. Su flexibilidad y facilidad de uso la han convertido en una de las librerías más utilizadas en el ecosistema Arduino.
Esta librería, incluida en Arduino IDE 1.0 y versiones posteriores, se basa en la aclamada biblioteca NewSoftSerial de Mikal Hart, lo que garantiza una implementación sólida y probada en el tiempo. Es importante destacar que, aunque es una solución basada en software, SoftwareSerial es capaz de manejar velocidades de comunicación de hasta 115200 bits por segundo (bps), lo que la hace adecuada para una amplia gama de aplicaciones.
Funcionamiento Interno: La Magia de la Emulación
La clave de SoftwareSerial reside en su capacidad para "simular" la comunicación serie estándar (UART) a través de la manipulación de los estados HIGH y LOW de los pines digitales. En lugar de depender de un hardware específico para la temporización y el control de los bits, SoftwareSerial utiliza el procesador de Arduino para gestionar estos procesos. Esto implica que el microcontrolador dedica ciclos de CPU para leer y escribir los datos bit a bit, en contraste con el UART hardware que realiza estas operaciones de forma autónoma.
Una característica interesante es la opción de inverse_logic en su constructor. Esta permite invertir la señalización de los bits, lo cual es útil para interactuar con dispositivos que operan bajo un protocolo de lógica inversa. Por defecto, un nivel LOW (0 voltios) en el pin Rx se interpreta como un 0 bit y un nivel HIGH (5 voltios) como un 1 bit (estado de reposo). Con inverse_logic activado, esta interpretación se invierte, lo que proporciona mayor compatibilidad.
Creación de un Objeto SoftwareSerial
Para utilizar SoftwareSerial, primero debes incluir la librería y luego crear una instancia de un objeto SoftwareSerial, especificando los pines RX y TX que deseas utilizar. Por ejemplo:
#include <SoftwareSerial.h>
const byte rxPin = 2;
const byte txPin = 3;
SoftwareSerial mySerial(rxPin, txPin);
Aquí, rxPin es el pin donde el Arduino recibirá datos, y txPin es el pin desde donde transmitirá datos. Es crucial recordar que, aunque puedes crear múltiples objetos SoftwareSerial, solo uno puede estar activo (escuchando) a la vez para recibir datos.
Limitaciones Importantes a Considerar
A pesar de su gran utilidad, SoftwareSerial no está exenta de limitaciones, principalmente debido a su naturaleza basada en software. Comprender estas restricciones es fundamental para diseñar proyectos robustos y evitar frustraciones:
- Recepción Simultánea: Si utilizas múltiples puertos SoftwareSerial, solo uno puede recibir datos en un momento dado. Debes usar la función
listen()para seleccionar qué puerto está activo para la recepción. Los datos que lleguen a otros puertos mientras no están "escuchando" serán descartados. - Pines RX Específicos en Placas Avanzadas: No todos los pines digitales en placas como Arduino Mega y Mega 2560, o Leonardo y Micro, soportan las interrupciones de cambio de nivel necesarias para una recepción fiable. Esto significa que los pines que pueden ser utilizados para RX son limitados:
- Mega y Mega 2560: 10, 11, 12, 13, 14, 15, 50, 51, 52, 53, A8 (62), A9 (63), A10 (64), A11 (65), A12 (66), A13 (67), A14 (68), A15 (69).
- Leonardo y Micro: 8, 9, 10, 11, 14 (MISO), 15 (SCK), 16 (MOSI).
- Rendimiento en Arduino/Genuino 101: En estas placas, la velocidad máxima de recepción (RX) está limitada a 57600 bps. Además, el pin 13 no funciona para RX en estas placas.
- Desbordamiento del Búfer: El búfer de recepción de SoftwareSerial tiene un tamaño limitado de 64 bytes. Si se reciben datos más rápido de lo que el programa puede leerlos, o si el búfer se llena mientras otro puerto está escuchando, se producirá un desbordamiento y los datos se perderán.
- Sincronización y Precisión: Al ser una implementación por software, la temporización puede ser menos precisa que la del hardware UART, especialmente a velocidades de baudios muy altas o cuando el microcontrolador está ocupado con otras tareas intensivas en tiempo.
Si tu proyecto requiere flujos de datos simultáneos sin interrupciones o una mayor precisión en la temporización, es recomendable explorar alternativas como la librería AltSoftSerial de Paul Stoffregen. AltSoftSerial supera algunas de las limitaciones de SoftwareSerial, aunque también tiene sus propias particularidades que deben ser investigadas en su documentación.
Funciones Clave de la Librería SoftwareSerial
La librería SoftwareSerial provee un conjunto de funciones que permiten una interacción completa con los puertos serie emulados, de manera muy similar a cómo se interactúa con el objeto Serial del puerto serie hardware. A continuación, se detallan las funciones más importantes:
Constructor: SoftwareSerial(rxPin, txPin, inverse_logic)
- Descripción: Se utiliza para crear una nueva instancia de un objeto SoftwareSerial. Debes especificar los pines digitales que actuarán como receptor (RX) y transmisor (TX). El argumento
inverse_logices opcional (por defecto esfalse) y permite invertir la polaridad de la señal serie, útil para ciertos dispositivos. - Parámetros:
rxPin: El pin digital de Arduino en el que se recibirán los datos serie.txPin: El pin digital de Arduino desde el que se transmitirán los datos serie.inverse_logic(opcional): Un valor booleano (truepara lógica inversa,falsepara lógica normal).
- Advertencia: Asegúrate de que los niveles de voltaje de los dispositivos externos estén dentro del rango de operación de tu Arduino (normalmente 0-5V para placas de 5V o 0-3.3V para placas de 3.3V). Conectar voltajes fuera de este rango puede dañar tu placa.
available()
- Descripción: Devuelve el número de bytes (caracteres) que están disponibles en el búfer de recepción del puerto serie software y listos para ser leídos. Estos son datos que ya han llegado y han sido almacenados.
- Sintaxis:
mySerial.available() - Retorna: Un entero que representa el número de bytes disponibles.
begin(speed)
- Descripción: Configura la velocidad de transmisión (baudios) para la comunicación del puerto serie software. Es una llamada esencial para inicializar el puerto antes de usarlo.
- Parámetros:
speed: La velocidad de transmisión en baudios (por ejemplo, 9600, 19200, 115200). Las velocidades admitidas son: 300, 600, 1200, 2400, 4800, 9600, 14400, 19200, 28800, 31250, 38400, 57600 y 115200.
- Ejemplo de uso: Después de crear el objeto SoftwareSerial, en la función
setup(), llamarías amySerial.begin(9600);para establecer la velocidad de 9600 baudios.
isListening()
- Descripción: Prueba si la instancia específica de SoftwareSerial está actualmente configurada para escuchar activamente los datos entrantes. Recuerda que solo una puede escuchar a la vez.
- Sintaxis:
mySerial.isListening() - Retorna: Un valor booleano (
truesi está escuchando,falseen caso contrario).
overflow()
- Descripción: Permite verificar si se ha producido un desbordamiento en el búfer de recepción de SoftwareSerial. Un desbordamiento ocurre cuando llegan más datos de los que el búfer de 64 bytes puede almacenar antes de que el programa los lea, lo que resulta en la pérdida de datos. Al llamar a esta función, se borra la bandera de desbordamiento.
- Sintaxis:
mySerial.overflow() - Retorna: Un valor booleano (
truesi hubo desbordamiento,falseen caso contrario).
peek()
- Descripción: Devuelve el siguiente carácter disponible en el búfer de recepción sin eliminarlo. Esto significa que las llamadas posteriores a
peek()devolverán el mismo carácter hasta que se lea conread(). - Sintaxis:
mySerial.peek() - Retorna: El carácter leído (como un
int), o-1si no hay datos disponibles.
read()
- Descripción: Lee el siguiente carácter disponible del búfer de recepción y lo elimina del búfer.
- Sintaxis:
mySerial.read() - Retorna: El carácter leído (como un
int), o-1si no hay datos disponibles.
print(data) y println(data)
- Descripción: Estas funciones se utilizan para transmitir datos al pin TX del puerto serie software. Funcionan de manera idéntica a
Serial.print()ySerial.println(), permitiendo imprimir diferentes tipos de datos (números, cadenas, caracteres) en varios formatos (decimal, hexadecimal, binario, etc.).println()añade un carácter de retorno de línea al final. - Parámetros: Varían según el tipo de dato a imprimir.
- Retorna: El número de bytes escritos.
listen()
- Descripción: Es una función crucial cuando se utilizan múltiples puertos SoftwareSerial. Permite seleccionar qué instancia de SoftwareSerial debe estar activa para recibir datos. Solo un puerto puede estar escuchando a la vez; los datos que lleguen a otros puertos mientras no están escuchando serán ignorados. Cualquier dato ya en el búfer de la instancia actual se descarta al llamar a
listen()a menos que ya estuviera escuchando. - Sintaxis:
mySerial.listen() - Retorna: Ninguno.
write(data)
- Descripción: Transmite datos al pin TX del puerto serie software como bytes en bruto. Es útil para enviar datos binarios o para un control más preciso de la transmisión.
- Sintaxis:
mySerial.write(valor)omySerial.write(buffer, longitud) - Retorna: El número de bytes escritos.
- Ejemplo:
mySerial.write(65);enviaría el carácter 'A'.mySerial.write("Hola");enviaría la cadena "Hola" como una secuencia de bytes.
Comparación: Hardware Serial vs. SoftwareSerial vs. AltSoftSerial
Entender las diferencias entre las opciones de comunicación serie disponibles en Arduino es clave para elegir la herramienta adecuada para cada proyecto. Aquí una tabla comparativa:
| Característica | Puerto Serie Hardware (UART) | SoftwareSerial | AltSoftSerial |
|---|---|---|---|
| Implementación | Hardware dedicado (chip ATmega) | Emulación por software | Emulación por software optimizada |
| Pines Usados | Pines 0 (RX) y 1 (TX) | Cualquier pin digital (con restricciones RX en algunas placas) | Pines específicos (generalmente 8 y 9 en la mayoría de Arduinos) |
| Recepción Simultánea | Sí (si la placa tiene múltiples UART) | No (solo uno escucha a la vez) | Sí (un puerto AltSoftSerial puede recibir mientras otro SoftwareSerial transmite) |
| Uso de CPU | Mínimo (UART maneja la mayoría) | Alto (CPU maneja la temporización y bits) | Moderado (más eficiente que SoftwareSerial) |
| Velocidad Máxima | Muy alta (hasta 2 Mbps o más) | Hasta 115200 bps (con limitaciones en algunas placas) | Generalmente 115200 bps (más fiable a altas velocidades) |
| Precisión | Muy alta | Variable, puede ser menos precisa a altas velocidades o con otras tareas | Alta, mejor que SoftwareSerial para temporización crítica |
| Búfer de Recepción | 64 bytes (hardware) | 64 bytes (software) | Generalmente más grande o más eficiente |
| Casos de Uso Ideal | Depuración, comunicación principal con PC, alta velocidad | Añadir un puerto serie adicional para un dispositivo secundario | Cuando se necesita un segundo puerto serie fiable para recepción simultánea o alta velocidad |
Consideraciones Adicionales y Mejores Prácticas
Al trabajar con SoftwareSerial, ten en cuenta los siguientes puntos para optimizar tu proyecto:
- Elección de Pines: Aunque SoftwareSerial puede usar "cualquier" pin digital, es vital revisar las limitaciones de pines RX para tu placa específica (Mega, Leonardo, etc.) para asegurar la funcionalidad.
- Gestión de la Recepción: Si tienes varios dispositivos enviando datos, implementa una lógica cuidadosa con
listen()para cambiar entre puertos y no perder información. Prioriza la lectura de datos conavailable()yread()para vaciar el búfer rápidamente. - Niveles de Voltaje: Siempre verifica los requisitos de voltaje de los dispositivos externos. Si un dispositivo opera a 3.3V y tu Arduino a 5V, necesitarás un conversor de nivel lógico (level shifter) para evitar daños.
- Depuración: Cuando uses SoftwareSerial para comunicación con un dispositivo, tu puerto serie hardware (
Serial) queda libre para depuración. ¡Aprovecha esto! - Evitar Bloqueos: Las operaciones de SoftwareSerial son bloqueantes, es decir, mientras el software está "bit-banging" los datos, el microcontrolador no puede hacer otras cosas. Esto es más notorio a velocidades de baudios altas. Diseña tu código para que las operaciones serie sean lo más breves posible.
Ejemplos de Aplicación de SoftwareSerial
La librería SoftwareSerial se ilustra con ejemplos claros que demuestran su uso. El "Software Serial Example" básico muestra cómo inicializar y usar un único puerto SoftwareSerial para enviar y recibir datos. Por otro lado, el ejemplo "Two Port Receive" es fundamental para entender cómo manejar múltiples puertos seriales, haciendo uso de la función listen() para alternar la escucha entre ellos, lo que es crucial para proyectos con varios dispositivos.
Preguntas Frecuentes sobre SoftwareSerial Arduino
¿Puedo usar SoftwareSerial en cualquier pin digital?
Sí, la mayoría de los pines digitales pueden ser utilizados para la transmisión (TX) con SoftwareSerial. Sin embargo, para la recepción (RX), hay restricciones importantes en algunas placas Arduino como Mega, Mega 2560, Leonardo y Micro, debido a la necesidad de pines que soporten interrupciones de cambio de nivel. Consulta la sección de "Limitaciones" para ver los pines específicos.
¿Cuántos puertos SoftwareSerial puedo tener?
Puedes crear múltiples instancias de objetos SoftwareSerial en tu código. No hay un límite estricto en el número de objetos que puedes definir. Sin embargo, recuerda que solo una instancia de SoftwareSerial puede estar "escuchando" (recibiendo datos) activamente en un momento dado. Si necesitas recibir datos de múltiples fuentes simultáneamente, SoftwareSerial no es la solución ideal por sí sola; deberías considerar alternativas como AltSoftSerial o placas con múltiples UARTs hardware.
¿Es SoftwareSerial tan rápido como el puerto serie hardware?
No, SoftwareSerial no es tan rápido ni tan eficiente como el puerto serie hardware (UART). Al ser una implementación por software, utiliza ciclos de la CPU de Arduino para gestionar la comunicación, lo que puede afectar el rendimiento general del programa, especialmente a velocidades de baudios altas (por ejemplo, 115200 bps) o cuando el microcontrolador está realizando otras tareas intensivas. El puerto serie hardware maneja la comunicación de forma autónoma, liberando la CPU.
¿Cuándo debo usar SoftwareSerial en lugar del puerto serie hardware?
Debes usar SoftwareSerial cuando necesites más de un puerto serie en tu proyecto. El puerto serie hardware (pines 0 y 1) se usa a menudo para depuración o comunicación con el ordenador a través del USB. Si necesitas conectar otro dispositivo serie (como un módulo GPS, Bluetooth, o un sensor que envía datos serie) y mantener libre el puerto hardware, SoftwareSerial es la solución perfecta. También es útil si el puerto hardware ya está ocupado por otro componente o si los pines 0 y 1 no son convenientes en tu diseño.
¿Qué es AltSoftSerial y cuándo debo considerarlo?
AltSoftSerial es una librería alternativa a SoftwareSerial, desarrollada por Paul Stoffregen, que ofrece un rendimiento superior y mayor fiabilidad, especialmente a altas velocidades y en escenarios donde se necesita una recepción más robusta o incluso la posibilidad de una recepción semi-simultánea (un puerto AltSoftSerial puede recibir mientras otro SoftwareSerial transmite). Debes considerarla si SoftwareSerial presenta problemas de rendimiento, pérdida de datos o si tus requisitos de temporización son más estrictos. Sin embargo, AltSoftSerial tiene sus propias restricciones en cuanto a los pines que puede usar.
¿Qué significa inverse_logic en SoftwareSerial?
El parámetro inverse_logic en el constructor de SoftwareSerial permite invertir la polaridad de la señal de comunicación serie. Normalmente, un nivel de voltaje bajo (0V) representa un bit '0' y un nivel alto (5V o 3.3V) representa un bit '1' o el estado de reposo. Si inverse_logic se establece en true, esta interpretación se invierte: un LOW se considera un '1' (o reposo) y un HIGH se considera un '0'. Esto es útil para interactuar con dispositivos que utilizan una convención de señalización serie invertida.
¿Cuál es el tamaño del búfer de recepción de SoftwareSerial?
El búfer de recepción de SoftwareSerial tiene un tamaño fijo de 64 bytes. Esto significa que puede almacenar hasta 64 caracteres o bytes de datos antes de que se produzca un desbordamiento si no se leen a tiempo. Es importante monitorear este búfer con available() y leer los datos con read() o peek() regularmente para evitar la pérdida de información.
La librería SoftwareSerial es una herramienta poderosa y versátil para expandir las capacidades de comunicación de tu Arduino. Aunque tiene sus particularidades y limitaciones, comprender cómo funciona y cómo aplicarla correctamente te permitirá desarrollar proyectos más complejos y con mayor conectividad. ¡Experimenta con ella y lleva tus creaciones al siguiente nivel!
Si quieres conocer otros artículos parecidos a Desvelando SoftwareSerial en Arduino: Guía Completa puedes visitar la categoría Librerías.
