concatenacion de valores numericos a traves del puerto serial

muy buenas tengan todos, mi problema es el siguiente: estoy haciendo un programa de control de trayectorias para un brazo robótico a través de matlab y arduino. el caso es que con matlab genero valores numéricos que corresponden al numero de grados que debe girar cada motor a fin que el robot pueda mantener la trayectoria especificada. estos valores los envió por medio serial hacia la tarjeta at mega de arduino, pero esta lo que hace es dividirme las cifras en partes, por ejemplo si envió el numero 125 a la tarjeta esta me recibe el 1 luego el 2 y por ultimo el 5.

quiero saber como hacer para recuperar el valor numérico que envié a través de matlab inicialmente. o sea como volver a unir el 125, en el caso del ejemplo.

como ya se habrán dado cuenta los que leyeron esto, mis conocimientos en programación son paupérrimos. cualquier ayuda al respecto sera bienvenida.

muchas gracias.

Hola buenos dias, en primer lugar nos deberias de explicar como recibes los datos en el arduino me explico si lo estas recibiendo como char como byte como int, etc.. Ahora un ejemplo a modolo de algoritmo es el siguiente: 1. recibes el primer char 1 como ya tu cifra es definica en 3 caracteres tienes que tener ya calara tu ecuacion. Ese primer car lo debes de llevar a int de la manera siguiente; valor recibido menos '0'. eso te dara 1 entero 31-30=1. 2. como tu cantidad de caracteres es 3 el primer caracter lo deves de multiplicar por 100. 3 recibes el segundo caracter en tu caso 2 igual lo llevas a entero restando '0' y obtienes 2 entero. 4 como es el segunto caracter lo multiplicas por 10. 5 recibes el tercer y ultimo caracter en tu caso 5 igual lo llevas a entero restando '0' y te quedara un entero 5 y esta por ser la ultima cifra no debes de multiplicarla por nada.

La ecuacion final quedaria de4 la guiente manera= c1*100+c2*10+c3; donde c1=1, c2=2 y c3=5 ct=125 ya en entero.

Saludos y espero haverte ayudado haaa otra manera mas logica seria declarar un arreglo char. ejemplo: char valor recibido[2]=0;

luego de eso vas recibiento tus valkores y con un condator vas incrementando el valor recibido de esa manera cuando ya tengas los 3 valores solo restara pasar el valor recibido a entero porque tya de manera automatica esta concatenado.

Alguna vez se ha contestado esto.

http://arduino.cc/forum/index.php/topic,62153.msg450226.html#msg450226

Si no vas a utilizar un caracter de control para saber donde acaba y termina un caracter es posible que el pic tenga un error de lectura del puerto serie y se coma una cifra por lo que todas las demas cifras estarán mal. si utilizas el caracter de control solo te fallará 1 cifra y las demás las volverá a interpretar bien.

El problema de como lo hace astrocar es que el código vale siempre para valores de 3 cifras en cuanto mandes de 1 o 2 cifras ya te lo interpreta mal.

otra forma de hacerlo es por lineas, si mandas los valores de los motores en lineas y al final hay un return ( char==13) entonces hay otra forma. al ser las posiciones de los valores fijos puedes calcularel valor del strng y pasarlo a int.

Tengo el codigo hecho en funciones además para esta ultima forma, mas que lo tengo en otro ordenador, en cuanto vuelva de vacas lo subo al playground o al foro.

te recomiendo la primer forma que te digo, con el caracter de control despues de enviar un valor.

un saludo

ok yo lo explique de la manera anterior porque el colega hace referencia a 125 es decir 3 caracteres pero si la cantidad es variable entonce hay que hacer como dice el colega Dongato usar cun caracter para control de final. y un contador para saber el numero de caracteres que llegaron y segun eso se replantea la nueva ecuacion que no es mas que multiplos de unidades, decenas, centenas y unidad de mil, etc.

Saludos y te comento que en la actualidad estoy haciendo algo parecido por noi decir igual pero es lo mismo envio via serial y tengo que ordenarla en el arduino.

Saludos y estamos en contacto.

bueno, estos días he realizado el siguiente código en el entorno de arduino para probar la concatenación:

#include <Servo.h>

Servo motor;
int incomingByte[3] = {0,0,0}; //matris de bytes que almacenará los valores ingresados

void setup()
{
Serial.begin(9600);//apertura del puerto serial a 9600 bps
motor.attach(4);//asignación del pin 4 digital

}

void loop()
{
if (Serial.available() > 0)
{
int i;
for (i = 0; i < 3; i = i+1)
{
incomingByte = Serial.read();// lee el byte entrante y lo almacena en la posición i
_ Serial.println(incomingByte*);[/u]_
_[u]
}[/u]_
_[u]
int num1 = incomingByte[0];[/u]_
_[u]
int num2 = incomingByte[1];[/u]_
_[u]
int num3 = incomingByte[2];[/u]_
_ int num = (num1 - 48)*100 + (num2 - 48)*10 + num3 - 48;_
_[u]
Serial.println(num);[/u]_
_[u]
motor.write(num);//actuamos el ángulo ingresado sobre el motor*[/u]_
}
}
el código funciona bien, pero cuando en el código retiro la línea que imprime la matriz incomingByte (subrayada), el motor responde con unos ángulos muy diferentes a los ingresados. debo añadir que sin esta modificación el motor sigue el ángulo especificado.

te puede ayudar este post

http://arduino.cc/forum/index.php/topic,69309.0.html

como se te ha explicado antes la condicion para que deje de calcular no es la longitud de los caracteres sino un caracter de referencia.

tu envias por puerto serie 124$76$76$9$189$123$

de esta manera primero calcula 124 llega $ y admite el valor, luego 76 y asi sucesivamente.

no pongas el for de 0 a 3 porque si solo vienen 2 numero no lo puedes calcular bien.

el codigo que viene en el post antes referenciado te puedes hacer una idea de como se hace

un saludo

muchas gracias SrDonGato, la verdad, al principio no le entendía lo que intentaba decirme pero ya lo veo claro, el problema que me plantea. hasta ahora he realizado este código para almacenar una serie de valores ingresados, en una matriz de 4x3, pero como ud comentaba en este programa al enviar los datos debo hacerlo de seguido. me explico:
si quiero enviar 123, 456, 789 y 246 debo escribir en el monitor serial 123456789246.

int incomingbyte[4][3]; //matriz de datos (byte) leidos

/*Declaramos las variables correspondientes a los pines que
encenderán o apagarán a medida que llegan las instrucciones*/

//int LedPin13 = 13; //Pin 13 donde el LEDse apagará o encenderá dependiendo de los dattos recibidos
//int LedPin10 = 10;
//int LedPin7 = 7;
//int LedPin3 = 3;


void setup()
{
  Serial.begin(9600); //abrir puerto serial y estblecer la velocidad en baudios (bps)
  //abrimos los pines como puertos de salida//
//  pinMode(LedPin13, OUTPUT);
//  pinMode(LedPin10, OUTPUT);
//  pinMode(LedPin7, OUTPUT);
//  pinMode(LedPin3, OUTPUT);
}


void loop()
{
  if(Serial.available() > 0)
  {
    int i;
    int j;
    for(i = 0; i < 4; i = i + 1)
    {
      for(j = 0; j < 3; j = j + 1)
      {
        incomingbyte[i][j] = Serial.read();   // lee el byte entrante
        Serial.println(incomingbyte[i][j]);
      }
    }
  }    
      
      
//  int x = incomingbyte - 48;
//  if(x > 5)
//  {
//   digitalWrite(LedPin, HIGH);//encender el LED 
//   delay(1000);
//   digitalWrite(LedPin, LOW);//apagar el LED
// 
//    //  Serial.print("Recibo: "); //dice lo que ha recibido
//    Serial.println(x,DEC);
//  }
}

mi otra pregunta sería entonces, como enviaría estos datos a través de matlab si declaro esa variable de control ‘$’???

Muchas gracias por la ayuda suministrada
Pd: el código anteriormente posteado, el del servomotor, no necesita ya de tres cifras.

ahora que logre enviar datos a matlab, hice un código que me enviará una serie de datos a cada led, matrices de datos
ahora me pasa algo chistoso, cuando ejecuto el script, no me envia los datos a la tarjeta. pero si escriobo la ultima linea del script en el command window de matlab, los leds empiezan a encenderse y apagarse como lo deseaba. estos son los códigos. primero el de arduino

//Comunicación serial MatLab-Arduino

int incomingbyte[4][3]; //matriz de datos (byte) leidos

/*Declaramos las variables correspondientes a los pines que
encenderán o apagarán a medida que llegan las instrucciones*/

int LedPin13 = 13; //Pin 13 donde el LEDse apagará o encenderá dependiendo de los dattos recibidos
int LedPin10 = 10;
int LedPin7 = 7;
int LedPin3 = 4;


void setup()
{
  Serial.begin(9600); //abrir puerto serial y estblecer la velocidad en baudios (bps)
  //abrimos los pines como puertos de salida//
  pinMode(LedPin13, OUTPUT);
  pinMode(LedPin10, OUTPUT);
  pinMode(LedPin7, OUTPUT);
  pinMode(LedPin3, OUTPUT);
}


void loop()
{
  if(Serial.available() > 0)
  {
    int i;
    int j;
    for(i = 0; i < 4; i = i + 1)
    {
      for(j = 0; j < 3; j = j + 1)
      {
        incomingbyte[i][j] = Serial.read();   // lee el byte entrante
        Serial.println(incomingbyte[i][j]);
        
      }
    }
    int tiempo[4];
    int g;
    for(g = 0; g < 4; g = g + 1)
    {
      tiempo[g] = (incomingbyte[g][0] - 48)*100 + (incomingbyte[g][1] - 48)*10 + (incomingbyte[g][2] - 48);
      Serial.println(tiempo[g]);
    }

    digitalWrite(LedPin13, HIGH);//encender el LED
    delay(tiempo[0]*10);
    digitalWrite(LedPin13, LOW);//apagar el LED
    digitalWrite(LedPin10, HIGH);
    delay(tiempo[1]*10);
    digitalWrite(LedPin10, LOW);
    digitalWrite(LedPin7, HIGH);
    delay(tiempo[2]*10);
    digitalWrite(LedPin7, LOW);
    digitalWrite(LedPin3, HIGH);
    delay(tiempo[3]*10);
    digitalWrite(LedPin3, LOW);
  }
}

ahora el de matlab:

%Comunicación serial Arduino-MatLab
delete(a);
clear all;
close all;
a = serial('COM3','BaudRate',9600);
fopen(a);
b = [100;200;300;400];
c = [200;300;400;100];
d = [300;400;100;200];
e = [400;100;200;300];
k = size(b);

bs = num2str(b);
cs = num2str(c);
ds = num2str(d);
es = num2str(e);
for i = 1:  k(1)
    send(i,1:12) = strcat(bs(i,1:3),cs(i,1:3),ds(i,1:3),es(i,1:3));
end
sis = size(send);
sendt = send';
for i = 1: sis(1)*sis(2)
    sendr(i) = sendt(i);
end
fwrite(a,sendr)

Por favor ayudenme con esta

no se de matlab pero este comando

send(i,1:12) = strcat('$')

te enviaría el caracter $ ?

ese comando concatena dos cadenas de caracteres

si puedes enviar el caracter ese despues de cada numero con el código que te dejé lo tienes

creo que te has complicado mucho la vida :slight_smile:

veamos, el codigo de matlab

b = [100;200;300;400];

c = [200;300;400;100];
d = [300;400;100;200];
e = [400;100;200;300];

intuyo que quieres mandar los 16 valores, o sea. 100, 200, 300, 400, 200 … 200, 300.

intuyo que quieres leer estos valores con este codigo

  if(Serial.available() > 0)

{
    int i;
    int j;
    for(i = 0; i < 4; i = i + 1)
    {
      for(j = 0; j < 3; j = j + 1)
      {
        incomingbyte[i][j] = Serial.read();  // lee el byte entrante
        Serial.println(incomingbyte[i][j]);
       
      }
    }

vas a tener carios problemas.
1º no puedes enviar valores mayores de 255 (un caracter es de 0 a 255)
2º el microcontrolador va mas rapido que la comunicacion serie por loq ue siempre te machacará la/las primeras posicines de incomingbyte

fijate en el codigo que hice. primero recibe una linea entera, o por marcador de posicion de numero o por numero de caracteres recividos, es decir haces un buffer de entrada largo, y luego lo procesas de una vez. si son 16 valores coge 16 bites ( valores de 0 a 255) y si son caracteres debes pasarlo a numero entonces 3 caracteres por 16, 48 caracteres de buffer.

espero haberme explicado

un saludo