Problema con buffer serial

Hola,
soy nuevo en este foro, (y en los trapicheos con mi nuevo Arduino Uno...), tengo conocimiento de lenguaje de programación y de electrónica, sin embargo me quedé bloqueado con un problema tonto ya al principio de mis experimentos.

Me explico: estoy intentando controlar dos motores paso a paso para que me muevan una plataforma en un plano bidimensional (X,Y).
Hasta aquí ningún problema, ya tengo la electrónica de control, y durante la pruebas, conseguí controlar los dos motores con dos potenciómetros sin problema.

Ahora querría controlar la posición enviando desde puerto serial las coordenadas en formato (XXX,YYY) para que los dos motores llegaran a la coordenada enviada, y aquí empieza mi problema: creo 2 buffers para las coordenadas, cada uno de 3 Bytes pero al intentar llenarlos me repite el ciclo y pierde los datos... Mejor os pongo el código de prueba:

#include <stdlib.h>    
char X_buffer[3];
char Y_buffer[3];
int received;
int i=0;
int j=0;
int X_pos=0;
int Y_pos=0;

void setup()
{
    Serial.begin(9600);
    received = 0;
    X_buffer[received] = '\0';
    Y_buffer[received] = '\0';
    Serial.println("setup");
}
void loop()
{
    if (Serial.available())
      {
        delay(100);
	// Get x cord
	  for(i=0; i<3; i++)
	    {
	    X_buffer[i] = Serial.read();
            Serial.print("El caracter ");
            Serial.print(i+1);
            Serial.print(" de X es ");
            Serial.println(X_buffer[i]);
	    }    
        X_pos = atoi(X_buffer);
        Serial.print("X_buffer =");
        Serial.println(X_buffer);
        Serial.print("X_pos =");
        Serial.println(X_pos,DEC);        
	  // Get y cord
	  for(j=0; j<3; j++)
	    {
	    Y_buffer[j] = Serial.read();
            Serial.print("El caracter ");
            Serial.print(j+1);
            Serial.print(" de Y es ");
            Serial.println(Y_buffer[j]);
	    }	        
	Y_pos = atoi(Y_buffer);
        Serial.print("Y_buffer =");
        Serial.println(Y_buffer);
        Serial.print("Y_pos =");
        Serial.println(Y_pos,DEC);
        Serial.println("fin");    
      }
//Serial.print("X_buffer =");
//Serial.println(X_buffer);
//Serial.print("X_pos =");
//Serial.println(X_pos,DEC);
received = 0;
//Serial.println("Espero 1000");
delay(1000);
}

y este es el resultado de insertar 123456 como coordenadas (equivaldría a (123,456)) desde el Serial Monitor:

setup
El caracter 1 de X es 1
El caracter 2 de X es 2
El caracter 3 de X es 3
X_buffer =123
X_pos =123
El caracter 1 de Y es 4
El caracter 2 de Y es 5
El caracter 3 de Y es 6
Y_buffer =456
Y_pos =456
fin
El caracter 1 de X es 

El caracter 2 de X es ÿ
El caracter 3 de X es ÿ
X_buffer =
ÿÿ456
X_pos =0
El caracter 1 de Y es ÿ
El caracter 2 de Y es ÿ
El caracter 3 de Y es ÿ
Y_buffer =ÿÿÿ
Y_pos =0
fin

Como podéis ver, la primera parte funciona de maravilla!! Lo que no entiendo (y lo que no consigo solucionar), es porqué sigue después del primer fin... Parece que se me cuele algo por el medio...
Seguro que es una chorrada, pero espero que alguien me pueda echar un cable.
Un saludo

Hola reex74.

He ejecutado el código que has puesto en mi arduino duemilanove y he obtenido los siguientes resultados:

Introduzco 123456

setup
El caracter 1 de X es 1
El caracter 2 de X es 2
El caracter 3 de X es 3
X_buffer =123
X_pos =123
El caracter 1 de Y es 4
El caracter 2 de Y es 5
El caracter 3 de Y es 6
Y_buffer =456
Y_pos =456
fin

A mí no se me ejecutado 2 veces se me queda ahí esperando que se introduzca otro valor y al introducirlo me da lo siguiente:

Después de 123456 introduzco 654321

setup
El caracter 1 de X es 1
El caracter 2 de X es 2
El caracter 3 de X es 3
X_buffer =123
X_pos =123
El caracter 1 de Y es 4
El caracter 2 de Y es 5
El caracter 3 de Y es 6
Y_buffer =456
Y_pos =456
fin
El caracter 1 de X es 6
El caracter 2 de X es 5
El caracter 3 de X es 4
X_buffer =654456
X_pos =-904
El caracter 1 de Y es 3
El caracter 2 de Y es 2
El caracter 3 de Y es 1
Y_buffer =321
Y_pos =321
fin

Como se puede observar la variable X_buffer =654456 y debería de ser 654, eso es porque imprimes X_buffer y busca el valor \0 para terminar y al no estar bien situado te la imprime mal, para solucionar el problema debes de poner \0 al final del array y el código quedaría así:

#include <stdlib.h>    
char X_buffer[4];
char Y_buffer[4];
int received;
int i=0;
int j=0;
int X_pos=0;
int Y_pos=0;

void setup()
{
    Serial.begin(9600);
    received = 0;
    X_buffer[3] = '\0';
    Y_buffer[3] = '\0';
    Serial.println("setup");
}
void loop()
{
    if (Serial.available())
      {
        delay(100);
	// Get x cord
	  for(i=0; i<3; i++)
	    {
	    X_buffer[i] = Serial.read();
            Serial.print("El caracter ");
            Serial.print(i+1);
            Serial.print(" de X es ");
            Serial.println(X_buffer[i]);
	    }    
        X_pos = atoi(X_buffer);
        Serial.print("X_buffer =");
        Serial.println(X_buffer);
        Serial.print("X_pos =");
        Serial.println(X_pos,DEC);        
	  // Get y cord
	  for(j=0; j<3; j++)
	    {
	    Y_buffer[j] = Serial.read();
            Serial.print("El caracter ");
            Serial.print(j+1);
            Serial.print(" de Y es ");
            Serial.println(Y_buffer[j]);
	    }	        
	Y_pos = atoi(Y_buffer);
        Serial.print("Y_buffer =");
        Serial.println(Y_buffer);
        Serial.print("Y_pos =");
        Serial.println(Y_pos,DEC);
        Serial.println("fin");    
      }
//Serial.print("X_buffer =");
//Serial.println(X_buffer);
//Serial.print("X_pos =");
//Serial.println(X_pos,DEC);
received = 0;
//Serial.println("Espero 1000");
delay(1000);
}

No sé si al hacer esto se solucionará el problema de repetirse el bucle, pero prueba a ver que tal, ya que al producirse este error no sé si puede afectar a algo más. Si sigue repitiéndose prueba a hacer if (Serial.available() > 0) a ver si se soluciona.

Saludos chato_sat.

Muchas gracias chato_sat.
Efectivamente no había caído en el problema del \0 final para la terminación del buffer, pero mi problema sigue igual.
También lo intenté con
if (Serial.available()>0)
o introduciendo un ciclo de espera:
while (!Serial.available()){}
Pero no se soluciona...
Lo que me parece raro es que el Arduino 2009 no tenga el mismo problema... Tendrá un bootloader distinto?
Saludos

Tienen bootloader distinto, pero el bootloader no hace nada una vez en funcionamiento

Prueba a poner Serial.flush(); al final

Creo haber encontrado el problema (estos son los problemas tontos que tenemos y nos hacen perder mucho tiempo XD). Mirando la consola de arduino he visto al lado de la velocidad de transmisión un desplegable con varias opciones, yo lo tengo en "no line ending" y funciona perfecto, he probado en todas las otras opciones y como manda el retorno de carro y algunas opciones más, me pasa lo mismo que a tí. Así que prueba cambiando la opción a "no line ending" y me cuentas que tal.

Saludos chato_sat.

Me co en to!!!
Si lo sabía que tenía que ser una tontería de las gordas!!

Era exactamente un problema de la consola serial, poniendo "No line ending", problema resuelto!!

Gracias a todos

Un saludo

"Me encanta que los planes salgan bien”

Coronel Anibal Smith (1960-????)

Ya veo que has conseguido solucionar tu problema. Yo tambien el mio aunque de forma diferente ya que no uso la consola de arduino si no un programa hecho en c#.

Mi proyecto es sobre el control de dos motores para posicionar un telescopio y hacer seguimiento de constelaciones.

Seguimos en contacto por si nos podemos ayudar.

Saludos

Hola Antonio,
Me gustaría poder ver tu codigo en C# (aunque yo trabajé en C++, no creo sea muy distinto).
Si quieres ver el codigo para controlar los dos motores por serial, aquí te lo dejo. (el numero a pasarle es del formato XXXYYY)

Mi siguiente paso sería intentar hacer un pequeño programa para pasarle las coordenadas al Arduino de forma continua, por ejemplo pasar la posicion del raton a serial para que los motores siguan la trayectoria.

Ya te contaré,
Riccardo

motor_doble.pde (2.74 KB)