serial código readString()

Hola a todos, necessito ayuda con el siguiente còdigo:

Desde la arduino numero 1 envio los siguiente datos:

12@34%56/78)91&23. Al final de la frase la termino con un punto, y las variables las separo con caracteres raros:

En la arduino numero 2 donde se reciben estos datos, es donde tengo el problema:

Con java, pondria el siguiente còdigo, però en arduino no termino de ver como funciona:

void serialEvent (Serial port) {
valor = port.readStringUntil('.');

// Remover el punto
valor = valor.substring(0, valor.length() - 1);

//Buscamos los divisores
index1 = valor.indexOf('@');
index2 = valor.indexOf('%');
index3 = valor.indexOf('/');
index4 = valor.indexOf(')');
index5 = valor.indexOf('&');

p1boton = valor.substring(index1+1, index2);
ypos1 = valor.substring(index2+1, index3);
p1ypos = Integer.parseInt(ypos1);

p2boton = valor.substring(index4+1, index5);
ypos2 = valor.substring(index5+1, valor.length());
p2ypos = Integer.parseInt(ypos2);

}

lo que hace esta parte del programa és recopilar todos los datos, y separarlos, però en c++(en codigo arduino), lo se muy bien como tendria que hacerlo.
Una ayudita la agradeceria mucho!!!
Gracias!

supongamos que

  #define NUM_DELIM 5 // 5 delimitadores

 char *str = "12@34%56/78)91&23";
 char *args[NUM_DELIM];

  delim = '@';
  /* Extraemos la primera palabra */
  tmp=strtok(str, delim);
  strcpy(args[num], tmp);
  num++;
// luego repites desde   delim = '@'; con el siguiente delimitador

Solo a titulo de sugerencia, no es la mejor opcion pero esto puedo funcionar.

Si solo vas a trabajar con datos numericos,puedes usar parseInt, que va leyendo numeros del buffer hasta encontrar un caracter:

if Serial.available(){
  // suponiendo tu cadena 12;34;56;78;91;23.   ,no es necesario diferentes separadores 
  //para 6 numeros:
  int index[6];
  for (byte cont = 0;cont < 6;cont ++){
    index[cont] = Serial.parseInt();
  }
}

esto solo si vas a trabajar con datos numericos,si tienes que enviar caracteres no sirve.tambien puedes añadir un codigo de inicio de cadena ,para saber donde empieza.

tambien tengo una rutina que separa todo usando el mismo delimitador.

#define MAX_CADENA 10

/**
 ******************************************************************
 * @brief Extrae palabras de una cadena y las coloca en un array
 *
 * @param orig     Cadena inicial
 * @param delim    Las palabras vendrán delimitadas por uno de los 
 *                 caracteres de esta cadena o sea ','            
 * @param args     Array donde separaremos cada palabra que luego usas para llenar la estruct.
 * @param max_args Número de palabras como máximo a extraer (tamaño
 *                 del array)
 *
 * @return Número de palabras extraídas. (max_args+1) si en la 
 *         cadena hay más de max_args palabras.
 *
 ******************************************************************/
int extrae_argumentos(char *orig, char *delim, char args[][MAX_CADENA], int max_args)
{
  char *tmp;
  int num=0;
  /* Reservamos memoria para copiar la candena ... pero la memoria justa */
  char *str = malloc(strlen(orig)+1);
  strcpy(str, orig);

  /* Extraemos la primera palabra */
  tmp=strtok(str, delim);
  do
    {
      if (num==max_args)
    return max_args+1;  /* Si hemos extraído más cadenas que palabras devolvemos */
                /* El número de palabras máximo y salimos */

      strcpy(args[num], tmp);   /* Copiamos la palabra actual en el array */
      num++;

      /* Extraemos la siguiente palabra */
      tmp=strtok(NULL, delim);
    } while (tmp!=NULL);

  return num; 
}

Hola surbyte,
he estado probando tu codigo, y va perfecto, pero el acoplarlo con el programa, tengo un problema:
Cadena orig, está en char*, y no consigo convertir la cadena del Serial, que la extraigo con String a Char*:

Es decir::

#define MAX_CADENA 10

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

void loop()
{

 String string1 = Serial.readStringUntil('.');  // Como convierto esto a Char*???
 string1.toCharArray( char* char2,76);
 int num_palabras = extrae_argumentos(char2, char *delim, char arg[MAX_CADENA], int max_args);

}

//Extraer
int extrae_argumentos(char *orig, char *delim, char args[][MAX_CADENA], int max_args)
{
  char *tmp;
  int num=0;
  /* Reservamos memoria para copiar la candena ... pero la memoria justa */
  char *str = malloc(strlen(orig)+1);
  strcpy(str, orig);

  /* Extraemos la primera palabra */
  tmp=strtok(str, delim);
  do
    {
      if (num==max_args)
    return max_args+1;  /* Si hemos extraído más cadenas que palabras devolvemos */
                /* El número de palabras máximo y salimos */

      strcpy(args[num], tmp);   /* Copiamos la palabra actual en el array */
      num++;

      /* Extraemos la siguiente palabra */
      tmp=strtok(NULL, delim);
    } while (tmp!=NULL);

  return num; 
}

Algo no me funciona i no se que hacer!!
Me podriais ayudar?? Gracias!

String stringOne = "123456789";
char charBuf[50];
stringOne.toCharArray(charBuf, 50) ;

un ejemplo apropiado.

o bien esto

char* string2char(String command){
    if(command.length()!=0){
        char *p = const_cast<char*>(command.c_str());
        return p;
    }
}

Muchas gracias por la ayuda, pero aun el codigo no funciona, me sale este error::

sketch_jun15c.ino: In function 'void loop()':
sketch_jun15c:18: error: invalid conversion from 'char' to 'char (*)[10]'
sketch_jun15c:18: error: initializing argument 3 of 'int extrae_argumentos(char*, char*, char (*)[10], int)'
sketch_jun15c.ino: In function 'int extrae_argumentos(char*, char*, char (*)[10], int)':
sketch_jun15c:28: error: invalid conversion from 'void*' to 'char*'

Aqui el codigo..:

#define MAX_CADENA 10

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

void loop()
{

 String string1 = Serial.readStringUntil('.');  // Como convierto esto a Char*???
 char charBuf[50];
 string1.toCharArray(charBuf, 50);
 //
 char* delim;
 char arg[MAX_CADENA];
 int max_args;
 int num_palabras = extrae_argumentos(charBuf, delim, arg[MAX_CADENA], max_args);

}

//Extraer
int extrae_argumentos(char *orig, char *delim, char args[][MAX_CADENA], int max_args)
{
  char *tmp;
  int num=0;
  /* Reservamos memoria para copiar la candena ... pero la memoria justa */
  char *str = malloc(strlen(orig)+1);
  strcpy(str, orig);

  /* Extraemos la primera palabra */
  tmp=strtok(str, delim);
  do
    {
      if (num==max_args)
    return max_args+1;  /* Si hemos extraído más cadenas que palabras devolvemos */
                /* El número de palabras máximo y salimos */

      strcpy(args[num], tmp);   /* Copiamos la palabra actual en el array */
      num++;

      /* Extraemos la siguiente palabra */
      tmp=strtok(NULL, delim);
    } while (tmp!=NULL);

  return num; 
}

Muchas gracias por la ayuda, si me pudieseis ayudar con esto...? Muuuchas graaacias!

Recien veo tu post. Ya me fijo. Y edito aquí

#define MAX_ARGS 10
#define MAX_CADENA 20


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

void loop() {

 String string1 = Serial.readStringUntil('.');  // poner el delimitador que gustes
 char * charBuf;
 char args[MAX_ARGS][MAX_CADENA]; // Para extrae_argumentos
 char strbuf[15];

 string1.toCharArray(charBuf, 76);
 int num_palabras = extrae_argumentos(charBuf, ".", args, MAX_ARGS);

 int i;

  if (num_palabras>MAX_ARGS)  {
      printf ("Se han devuelto más palabras del máximo\n");
      num_palabras=MAX_ARGS;
  }

  sprintf(strbuf, "CADENA: %s\n", charBuf);
  Serial.print(strbuf);

  for (i=0; i<num_palabras; i++) {
    sprintf(strbuf, "Palabra %d: \"%s\"\n", i, args[i]);
    Serial.print(strbuf);
  }
}

//Extraer
int extrae_argumentos(char *orig, char *delim, char args[][MAX_CADENA], int max_args)
{
  char *tmp;
  int num=0;
  /* Reservamos memoria para copiar la candena ... pero la memoria justa */
  char *str = (char *) malloc(strlen(orig)+1);

  strcpy(str, orig);

  /* Extraemos la primera palabra */
  tmp=strtok(str, delim);
  do
    {
      if (num==max_args)
    return max_args+1;  /* Si hemos extraído más cadenas que palabras devolvemos */
                /* El número de palabras máximo y salimos */

      strcpy(args[num], tmp);   /* Copiamos la palabra actual en el array */
      num++;

      /* Extraemos la siguiente palabra */
      tmp=strtok(NULL, delim);
    } while (tmp!=NULL);

  return num; 
}

No esta probado pero debería funcionar razonablemente.

Yendo a otra cosa distinta, en tu código original empleabas un "Serial Event", que corta el proceso para leer lo que esté entrando.

En arduino sería simplemente hacer una rutina lamada:

void serialEvent() {

O para puertos distintos, por ej:

void serialEvent1() {

Por lo demás parece que surbyte te ha contestado genial! :slight_smile:

arriazu:
Yendo a otra cosa distinta, en tu código original empleabas un "Serial Event", que corta el proceso para leer lo que esté entrando.

En arduino sería simplemente hacer una rutina lamada:

void serialEvent() {

O para puertos distintos, por ej:

void serialEvent1() {

Por lo demás parece que surbyte te ha contestado genial! :slight_smile:

serialEvent() no es una interrupcion propiamente dicha y no va interrumpir ningun proceso ,se llama una vez por cada iteracion del loop y se comprueba si hay datos en el buffer para ejecutar la funcion asociada,pero no va a detener la ejecucion del loop.

Gracias por el apunte Jose, por como está explicado en la documentación:

Called when data is available. Use Serial.read() to capture this data.

Yo pensé que sí que generaba una interrupción. Es bueno saberlo :slight_smile:

arriazu:
Gracias por el apunte Jose, por como está explicado en la documentación:

Yo pensé que sí que generaba una interrupción. Es bueno saberlo :slight_smile:

Si es confuso ,aqui lo indica:
http://www.arduino.cc/en/Tutorial/SerialEvent

Demonstrates use of the SerialEvent() function. SerialEvent() is called after a loop(), if there is serial data in the buffer.

muchas gracias, pero el codigo sigue sin funcionar, es decir entra perfectament en el arduino pero no lo procesa corectamente:
Des del arduino 1, envio todo esto:

  Serial3.print("_");
  Serial3.print(robot);
  Serial3.print(",");
  Serial3.print(state);
  Serial3.print(",");
  Serial3.print("v0");
  Serial3.print(",");
  Serial3.print(enviar_configuracio_s3); 
  Serial3.print(",");
  
  //BOTONES ( 1 = on    0 = off)
  Serial3.print(bt_1a);
  Serial3.print(",");
  Serial3.print(bt_1b);
  Serial3.print(",");
  Serial3.print(bt_2a);
  Serial3.print(",");
  Serial3.print(bt_2b);
  Serial3.print(",");
  Serial3.print(bt_3a);
  Serial3.print(",");
  Serial3.print(bt_3b);
  Serial3.print(",");
  Serial3.print(bt_4a);
  Serial3.print(",");
  Serial3.print(bt_4b);
  Serial3.print(",");
  Serial3.print(bt_5a);
  Serial3.print(",");
  Serial3.print(bt_5b);
  Serial3.print(",");
  Serial3.print(bt_6a);
  Serial3.print(",");
  Serial3.print(bt_6b);  
  Serial3.print(",");
  
  //x i y de joysticks  (hasta 4 numeros cada variable)
  Serial3.print(j_x1);
  Serial3.print(",");
  Serial3.print(j_y1);
  Serial3.print(",");
  Serial3.print(j_x2);
  Serial3.print(",");
  Serial3.print(j_y2);
  Serial3.print(",");
  Serial3.print(j_x3);
  Serial3.print(",");
  Serial3.print(j_y3);
  Serial3.print(",");
  Serial3.print(j_x4);
  Serial3.print(",");
  Serial3.print(j_y4);
  Serial3.print(",");
  Serial3.print(j_x5);
  Serial3.print(",");
  Serial3.print(j_y5);
  Serial3.print(",");
  Serial3.print(j_x6);
  Serial3.print(",");
  Serial3.print(j_y6);
  Serial3.print(",");
  Serial3.print(j_x7);
  Serial3.print(",");
  Serial3.print(j_y7);
  Serial3.print(",");

  //botones (1= on    0=off
  Serial3.print(jb_1);
  Serial3.print(",");
  Serial3.print(jb_2);
  Serial3.print(",");
  Serial3.print(jb_3);
  Serial3.print(",");
  Serial3.print(jb_4);
  Serial3.print(",");
  Serial3.print(jb_5);
  Serial3.print(",");
  Serial3.print(jb_6);
  Serial3.print(",");
  Serial3.print(jb_7);
  Serial3.println(".");

Las primeras variables que envio son de botones, 0 o 1, las segundas son de joysticks, que pueden enviar hasta 4 xifas cada variable (de 0 a 1023), i finalmente otra vez botones (0 o 1);

El codigo que me enviaste (MUUCHAS GRAACIAS!), lo he probado, pero no me convierte correctamente, de string a char*.

Segundo arduino:

#define MAX_ARGS 70
#define MAX_CADENA 90


void setup()
{
 Serial.begin(57600);
 Serial3.begin(57600);
}

void loop() {

 String string1 = Serial3.readStringUntil('.');  // poner el delimitador que gustes
 char * charBuf;
 char args[MAX_ARGS][MAX_CADENA]; // Para extrae_argumentos
 char strbuf[15];

 string1.toCharArray(charBuf, 600);
 int num_palabras = extrae_argumentos(charBuf, ".", args, MAX_ARGS);
Serial.print(charBuf[1]);
 int i;

  if (num_palabras>MAX_ARGS)  {
      printf ("Se han devuelto más palabras del máximo\n");
      num_palabras=MAX_ARGS;
  }

  sprintf(strbuf, "CADENA: %s\n", charBuf);
  Serial.print(strbuf);

  for (i=0; i<num_palabras; i++) {
    sprintf(strbuf, "Palabra %d: \"%s\"\n", i, args[i]);
    Serial.print(strbuf);
  }
}

//Extraer
int extrae_argumentos(char *orig, char *delim, char args[][MAX_CADENA], int max_args)
{
  char *tmp;
  int num=0;
  /* Reservamos memoria para copiar la candena ... pero la memoria justa */
  char *str = (char *) malloc(strlen(orig)+1);
 
  strcpy(str, orig);

  /* Extraemos la primera palabra */
  tmp=strtok(str, delim);
  do
    {
      if (num==max_args)
    return max_args+1;  /* Si hemos extraído más cadenas que palabras devolvemos */
                /* El número de palabras máximo y salimos */

      strcpy(args[num], tmp);   /* Copiamos la palabra actual en el array */
      num++;

      /* Extraemos la siguiente palabra */
      tmp=strtok(NULL, delim);
    } while (tmp!=NULL);

  return num; 
}

He estado rumiando mucho este codigo, pero no veo porque no me extrae la string, y porque no la convierte. Para probarlo he puesto varias chuletas al medio, y he visto que no me la convierte de String a Char*.

Muchas gracias, si alguien me pudiese ayudar..!

600 bytes.. guarda que tu RAM no es ilimitada
Yo que tu Memory Available y controla que no te estas quedando sin RAM.

Ya he probado memoryfree() y me dice que ahun tengo 136 bytes, por lo que la memoria no es un problema. Alguien sabe qual es el problema?

Mudhas gracias"!

136 bytes en ese momento, pone una advertencia para que salte si llega a 0.
Es decir mide MemoryFree y si llega a 0 que te lo advierta

ya he probado de poner el aviso, y ahún el codigo no funciona, tampoco el aviso sale por tanto si hay espacio. El problema esque no me llegan todas las variables que quiero leer, el emisor (arduino 1), envia esto:

0,0,0,0,0,0,0,0,1234,1234,1234,1234,1234,1234,1234,1234,0,0,0,0,0,0,0,0. \n

y el arduino 2, no me llegan todas las variables.

eloiquintana:
ya he probado de poner el aviso, y ahún el codigo no funciona, tampoco el aviso sale por tanto si hay espacio. El problema esque no me llegan todas las variables que quiero leer, el emisor (arduino 1), envia esto:

0,0,0,0,0,0,0,0,1234,1234,1234,1234,1234,1234,1234,1234,0,0,0,0,0,0,0,0. \n

y el arduino 2, no me llegan todas las variables.

Podria ser problema del buffer del serial que solo tiene 64 bytes y el mensaje que envias es mas largo .

Intentá con esto

#define SERIAL_BUFFER_SIZE 256

en la primer linea de tu código