arduino-array-separado-comas

Array separado por comas por puerto serie en Arduino

Llevamos una serie de entradas destinadas a profundizar en el uso del puerto serie en un procesador como Arduino. En esta entrada vamos a ver cómo recibir un array separado por comas.

Anteriormente hemos visto cómo recibir caracteres y cadenas de texto, y cómo recibir números enteros y en coma flotante. Junto a estas, recibir un array separado por comas es otra de las peticiones más habituales en cuanto a uso del puerto serie.

Por supuesto, aunque nos refiramos a array separado por comas, el código es extensible a cualquier otro separador, como punto, punto y coma, cualquier otro carácter que se necesitéis.

Pero, antes de abordar el problema, conviene que reflexionéis sobre por qué queréis recibir un array separado por comas. Si lo que queremos es enviar/recibir una serie de elementos (ints, floats…) entre dos dispositivos, es mejor definir una trama y enviar los bytes directamente.

Si por desconocimiento (o por vagancia), vamos a enviar una serie de elementos como un array separado por comas y luego realizar la conversión del texto, estamos haciendo el proceso ineficiente de forma innecesaria, tanto en velocidad como en carga de procesador.

Por tanto, no debemos usar un array separado por comas cuando controlemos ambos agentes (emisor y receptor). Es más, en este caso nunca deberíamos mandar nada que no sean bytes. Es así, los chicos grandes mandan bytes.

Lamentablemente, no siempre tenemos la posibilidad de definir el mensaje enviado/recibido. En ocasiones la trame nos vendrá definido por un dispositivo, o un servicio con el que queramos comunicarnos. En ese caso, aquí sí, no tendremos más remedio que tratar con el array separado por comas (o el separador que toque).

Afortunadamente, no es un proceso complicado. Como en las entradas anteriores, existe más de una forma de realizar el proceso, con sus ventajas y desventajas. Aquí cómo recibir el array con ayuda de la clase String y “a mano”.

En los ejemplos vamos a emplear un array de int, porque es el caso más sencillo y muy habitual, aunque es fácil modificarlo para recibir un float u otro tipo de variables.

La funciones DEBUG están únicamente para visualizar los resultados, cuando uséis este código podéis quitar las partes relativas a su definición y uso.

Recibir con clase string

El primer método vamos a usar la clase String, para recibir, dividir el array y realizar la conversión.

En primer lugar, leemos una línea entera con Serial.readStringUntil(). Posteriormente, dividimos y convertimos la cadena empleando las funciones de la clase String.


#define DEBUG_ARRAY(a) {for (int index = 0; index < sizeof(a) / sizeof(a[0]); index++)   {Serial.print(a[index]); Serial.print('\t');} Serial.println();};

String str = "";
const char separator = ',';
const int dataLength = 3;
int data[dataLength];

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

void loop()
{
  if (Serial.available())
  {
    str = Serial.readStringUntil('\n');
    for (int i = 0; i < dataLength ; i++)
    {
      int index = str.indexOf(separator);
      data[i] = str.substring(0, index).toInt();
      str = str.substring(index + 1);
    }
    DEBUG_ARRAY(data);
  }
}

Este método es sencillo y eficiente, y debería ser la opción preferida para recibir arrays separados por coma.

Recibir con char array y método naive

Si no podemos, o no queremos emplear las funciones de la clase String, podemos realizar el proceso “a mano”, lo cual ya nos hemos acostumbrado a denominar en entradas anteriores método “naive”.


#define DEBUG_ARRAY(a) {for (int index = 0; index < sizeof(a) / sizeof(a[0]); index++)   {Serial.print(a[index]); Serial.print('\t');} Serial.println();};

String str = "";
const char separator = ',';
const int dataLength = 3;
int dataArray[dataLength];
int data = 0;
int dataIndex = 0;

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

void loop()
{
  while (Serial.available())
  {
    char incomingChar = Serial.read();
    if (incomingChar >= '0' && incomingChar <= '9')
    {
      data = (data * 10) + (incomingChar - '0');
    }
    else if (incomingChar == separator)
    {
      dataArray[dataIndex] = data;
      if (++dataIndex >= dataLength) dataIndex = 0;
      data = 0;
    }
    else if (incomingChar == '\n')
    {
      dataArray[dataIndex] = data;
      data = 0;
      dataIndex = 0;
      DEBUG_ARRAY(dataArray);
    }
  }
}

El proceso no es mucho más complejo, aunque el código es más largo, por lo que sólo deberemos usarlo cuando realmente no sea posible emplear la clase String.

Librería EasyComma

¿Y si lo metemos en una librería? ¡Pues claro que sí! Aquí tenéis la librería EasyComma, que nos permite leer una serie de enteros delimitados por un separador (por defecto la coma) de forma cómoda y sencilla. ¡A disfrutar!.

Descarga el código

Todo el código de esta entrada está disponible para su descarga en Github. github-full