Publi

Formateando la salida en Serial para Arduino [1ª parte] ( y no sólo para Arduino )

Arduino - Minicom - Emacs Una de las cosas que más echo de menos programando con Arduino es el formateo de texto de cara al serial, ya que éste sólo permite cadenas de texto o números, y no todo junto. En principio es comprensible, el sistema debe estar en un tamaño muy reducido, y esta característica engordará el binario. como mínimo 1.5Kb; Podemos optar por varias soluciones que explicaré en este post:

  • sprintf()
  • Usando la clase String
  • vsnprintf()
  • Inventar nuestro printf() particular con salida a cadena
  • Inventar nuestro printf() particular con salida a Serial

Usando sprintf()

Esta forma es muy sencilla y engordará nuestro ejecutable 1.5Kb aproximadamente. Será útil cuando vayamos a formatear poco texto, en pocas salidas, ya que debemos almacenar en una variable la cadena resultante y luego esa cadena es la que podemos escribir en Serial; son 3 líneas de código por cada salida que vayamos a hacer:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
int contador=0;

void setup()
{
  Serial.begin(19200);
}

void loop()
{
  char texto[50];

  sprintf(texto, "Transcurridos %d segundos", contador++);
  Serial.write(texto);
  delay(1000);
}

Aunque con sprintf todo funciona bien, recomiendo utilizar snprintf() ya que a éste último le debemos decir el tamaño de la variable a escribir y si los valores hacen la cadena más larga de lo que debería, ésta será recortada, es decir, si reservamos 50 bytes para la cadena, con sprintf() tal vez se escriban más, depende de los datos a escribir, pero snprintf() escribirá 50.

1
  snprintf(texto, 50, "Transcurridos %d segundos desde la ultima vez que se nos ocurrio poner en pantalla el valor del contador", contador++);

Este ejemplo se recortará, por ejemplo, cuando contador vale 100 a:

Transcurridos 100 segundos desde la ultima vez qu

Usando la clase String

Es más estilo C++, pero la clase String nos permite hacer muchas cosas, entre ellas almacenar cadenas dinámicas y no tener que preocuparnos tanto por el tamaño de un array de caracteres, aunque en un ordenador no pasa nada, en los tiempos que corren tenemos memoria de sobra, pero un pequeño Arduino no tiene mucha, por lo que tenemos que procurar no pasarnos. Este método tiene dos inconvenientes: engordará el ejecutable 2.2Kb y sólo vale para pocas salidas formateadas porque son más líneas de código que antes; aunque algo más intuitivo (si te resulta incómoda la forma de formatear de printf(), aunque este método es menos potente).

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
int contador=0;

void setup()
{
  Serial.begin(19200);
}

void loop()
{
  String texto;
  texto="Transcurridos "+contador;
  texto=texto+" segundos desde la ultima vez que se nos ocurrio poner en pantalla el valor del contador";
  Serial.println(texto);

  delay(1000);
}

Usando vsnprintf()

Llegamos al primer método interesante y es que nos permitirá hacer múltiples salidas, incluso escribir una función con la que podemos crear esa salida. Este método incrementará el binario en 1.5Kb, y nos permitirá fácilmente añadir salidas formateadas al estilo printf(), para ello crearemos la función printSerial(), que aceptará múltiples argumentos y se los pasará a la función vsnprintf(). Para esta función también debemos saber el número de bytes que ocupará la cadena, por lo que estableceremos un máximo: MAX_CADENA.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
#include <stdarg.h>
#define MAX_CADENA 128
int contador=0;

void setup()
{
  Serial.begin(19200);
}

void printSerial(const char *fmt, ...)
{
  char tmp[MAX_CADENA];
  va_list args;

  // Obtenemos la lista de argumentos
  va_start (args, fmt );
  // Escribimos en tmp, con tamaño MAX_CADENA, la cadena de formato será fmt y los
  // argumentos args
  vsnprintf(tmp, MAX_CADENA, fmt, args);
  va_end (args);

  Serial.print(tmp);  
}

void loop()
{
  printSerial("Transcurridos %d segundos desde que se inicio.", contador++);

  delay(1000);
}

Y con una pequeña modificación podemos especificar en qué Serial escribir (si tenemos Arduino Mega, por ejemplo), por unos pocos bytes más:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
#include <stdarg.h>
#define MAX_CADENA 128
int contador=0;

void setup()
{
  Serial.begin(19200);
}

void printSerial(HardwareSerial &sp, const char *fmt, ...)
{
  char tmp[MAX_CADENA];
  va_list args;

  // Obtenemos la lista de argumentos
  va_start (args, fmt );
  // Escribimos en tmp, con tamaño MAX_CADENA, la cadena de formato será fmt y los
  // argumentos args
  vsnprintf(tmp, MAX_CADENA, fmt, args);
  va_end (args);

  sp.print(tmp);  
}

void loop()
{
  printSerial(Serial, "Transcurridos %d segundos desde que se inicio.", contador++);

  delay(1000);
}

Esta función podrá ser copiada en vuestro código o añadida como una librería.

También podría interesarte....

There are 3 comments left Ir a comentario

  1. Pingback: Bitacoras.com /

  2. Pingback: Poesía binaria » Formateando la salida en el Serial para Arduino [ parte II ] /

  3. The Warriors Vest /
    Usando Google Chrome Google Chrome 122.0.0.0 en Windows Windows NT

    This is a great inspiring article. I am pretty much pleased with your good work. You put really very helpful information.

Leave a Reply