Autor Tema: programa para graficar señales [pedido]  (Leído 15933 veces)

0 Usuarios y 1 Visitante están viendo este tema.

Desconectado gera

  • Colaborador
  • PIC24H
  • *****
  • Mensajes: 2188
Re: programa para graficar señales [pedido]
« Respuesta #15 en: 02 de Junio de 2012, 14:16:28 »
Marito, lo que pasa es q por el puerto serie tenes q enviar el dato codificado en ascii como una cadena, luego en processing lo lees y lo convertis al tipo de dato q quieras (entero, flotante..).
Te paso mi programa en processing:
Código: [Seleccionar]
import processing.serial.*;
Serial myPort;  // The serial port

float acc_angle=0;
float gyro_angle=0;
float angle=0;

void setup()
{
  size(650,300);
  println(Serial.list());
  myPort = new Serial(this, Serial.list()[0], 9600);
  myPort.write("m\r");
}


void draw ()
{
  while (myPort.available() > 0)
  {
    String recibido = myPort.readStringUntil('\n');
    if (recibido != null)
    {
      float[] val = float(split(recibido,","));
      drawGraph(val);
    }
  }
}

void drawGraph(float[] val)
{
  float x_acc = (val[0]-513)/97;
  float y_acc = (val[1]-500)/105;
  float z_acc = -(val[2]-511)/103;
  float gyro = -(val[3]-455)/67; //*0.015;
  float dt=0.1;
 
  acc_angle = atan(z_acc/y_acc);
  gyro_angle += gyro * dt;
 
  angle = (0.95)*(angle + gyro * dt) + (0.05)*(acc_angle);

 
  stroke(0);
  background(255);
  rectMode(CENTER);
  textSize(14);
 
  pushMatrix();
    fill(255,100,100);
    translate(100, 200);
    text("acc angle = " + degrees(acc_angle) + "º" ,-90,-100);
    rotate(acc_angle);
    rect(0, 0, 100, 30);
  popMatrix();

  pushMatrix();
    fill(100,255,100);
    translate(300, 200);
    text("gyro angle = " + degrees(gyro_angle) + "º" ,-90,-100);
    rotate(gyro_angle);
    rect(0, 0, 100, 30);
  popMatrix();

  pushMatrix();
    fill(100,100,255);
    translate(500, 200);
    text("filtered angle = " + degrees(angle) + "º" ,-90,-100);
    rotate(angle);
    rect(0, 0, 100, 30);
  popMatrix();
 

  /*strokeWeight(10);
  line(width/2 , height/2 +100, width/2 + v.x , height/2 + v.y +100);*/
}

En el pic tengo un programa que envia las lecturas del acelerometro y gyro sin procesar en este formato:
Código: [Seleccionar]
printf("%li,%li,%li,%li,%li,\n",val[0],val[1],val[2],val[3],val[4]);
Estoy mandando 5 enteros porq el ADC convierte a valores enteros, pero podes enviar flotantes tranquilamente, fijate en el codigo de processing que convierte todo a flotante en esta linea:
Código: [Seleccionar]
float[] val = float(split(recibido,","));
Aca va otro programa similar, pero que grafica en funcion del tiempo:
Código: [Seleccionar]
import processing.serial.*;
Serial myPort;  // The serial port
int i = 0;      // counter


void setup()
{
  size(800, 600);       
  println(Serial.list());
  myPort = new Serial(this, Serial.list()[0], 9600); // Serial.list()[0] modify that number if don't works
  background(255,255,255);
 
  //myPort.write(83);
}


void draw ()
{
  while (myPort.available() > 0)
  {
    String a0 = myPort.readStringUntil('\n');
   
    if (a0!=null)
    {
      float[] val = float(split (a0, ","));
      //println (val[0] + "," + val[1] + "," + val[2]);
      drawGraph_accel(val[0]*100,val[1]*100,val[2]*100);  //100 is a scale factor
    }
  }
}

void drawGraph_accel (float d_ax, float d_vx, float d_px)
{
  stroke(255,0,0,70);
  line(i, height/4, i, height/4 - d_ax);
  stroke(0,0,255,70);
  line(i, height/4*2, i, height/4*2 - d_vx);
  stroke(0,255,0,70);
  line(i, height/4*3, i, height/4*3 - d_px);
 
  if (i >= width-2)
  {
    i = 0;
    background(255,255,255);
  }
  else
  {
    i++;
  }
}

Podes modificar el programa a tu gusto para q se adapte a tus necesidades. cualquier duda avisame.
Saludos!

"conozco dos cosas infinitas: el universo y la estupidez humana. Y no estoy muy seguro del primero." A.Einstein

Desconectado marito

  • PIC16
  • ***
  • Mensajes: 217
Re: programa para graficar señales [pedido]
« Respuesta #16 en: 02 de Junio de 2012, 19:34:06 »
Gera muchas gracias por tu excelente explicación!

El %Li es para transmitir valores enteros en acsii?

Como haces la conversión de entero o flotante a acsii?

Como se definen variables acsii?
« Última modificación: 02 de Junio de 2012, 19:41:34 por marito »

Desconectado gera

  • Colaborador
  • PIC24H
  • *****
  • Mensajes: 2188
Re: programa para graficar señales [pedido]
« Respuesta #17 en: 02 de Junio de 2012, 20:17:56 »
Marito, el printf se encarga de convertir los valores. %li es para imprimir enteros largos (long int). Si la variable que queres imprimir es un flotante, tenes que usar %f.

"conozco dos cosas infinitas: el universo y la estupidez humana. Y no estoy muy seguro del primero." A.Einstein

Desconectado marito

  • PIC16
  • ***
  • Mensajes: 217
Re: programa para graficar señales [pedido]
« Respuesta #18 en: 03 de Junio de 2012, 11:10:18 »
Ah! Para enteros largos yo tengo que usar %lu, enteros %u y flotantes %f.

Para la prueba que estoy haciendo, estoy enviando un entero (%u) ya que por lo que leí en la ayuda de processing, se reciben enteros (16bits - 0..255) desde el puerto serie. Pero enviando el entero 171 desde mi pic con la instrucción:

Código: [Seleccionar]
printf(" %u ", datoentero);
Recibo un 32 en el processing con el comando

 
Código: [Seleccionar]
dato = puerto.read();


Desconectado gera

  • Colaborador
  • PIC24H
  • *****
  • Mensajes: 2188
Re: programa para graficar señales [pedido]
« Respuesta #19 en: 03 de Junio de 2012, 13:19:39 »
Es que lo estas leyendo mal.  Lo que hace read() es leer un solo caracter, cuando tu dato tiene 3 caracteres. Ademas lee ese dato como un entero, y tendrias q leerlo como cadena. La funcion que tenes q usar es readStringUntil().
Aca te dejo la referencia de ambas:
http://processing.org/reference/libraries/serial/Serial_read_.html
http://processing.org/reference/libraries/serial/Serial_readStringUntil_.html

En tu cadena tenes q poner un salto de linea al final (un punto o algo), entonces a readStringUntil() le pasa como parametro ese caracter para que sepa que ahi termina el dato. En el pic haces:
Código: [Seleccionar]
printf("%u\n",datoentero);
Y en processing
Código: [Seleccionar]
String myString = null;
...
myString = myPort.readStringUntil(lf);

Saludos!

"conozco dos cosas infinitas: el universo y la estupidez humana. Y no estoy muy seguro del primero." A.Einstein

Desconectado marito

  • PIC16
  • ***
  • Mensajes: 217
Re: programa para graficar señales [pedido]
« Respuesta #20 en: 04 de Junio de 2012, 21:10:03 »
Buenísimo Gera! Ya estoy recibiendo un entero!

Tenía que usar, tal como me dijiste, la sentencia ReadUntilString.

Muchas gracias! Ahora voy a trabajar para recibir flotantes para enviar los ángulos medidos por el giro y el acelerómetro.

Desconectado marito

  • PIC16
  • ***
  • Mensajes: 217
Re: programa para graficar señales [pedido]
« Respuesta #21 en: 05 de Junio de 2012, 08:48:00 »
Gera para enviar un número flotante tengo que hacer la conversión a doble entero (long Int) en el PIC antes de enviarlo?

Desconectado gera

  • Colaborador
  • PIC24H
  • *****
  • Mensajes: 2188
Re: programa para graficar señales [pedido]
« Respuesta #22 en: 05 de Junio de 2012, 13:00:32 »
Para enviar un flotante tenes que cambiar el printf nomas. Por ej:

Código: [Seleccionar]
float var1=3.14, var2=5.2, var3=6.4;
printf("%f,%f,%f,\n",var1,var2,var3);

Acordate que vos estas enviando una cadena (texto) por el puerto serie, no el numero. Por lo tanto podes enviar cualquier tipo de dato, que luego processing lo transforma a flotante.
Saludos!

"conozco dos cosas infinitas: el universo y la estupidez humana. Y no estoy muy seguro del primero." A.Einstein

Desconectado marito

  • PIC16
  • ***
  • Mensajes: 217
Re: programa para graficar señales [pedido]
« Respuesta #23 en: 05 de Junio de 2012, 13:07:35 »
Hola Gera;

He intentado enviar flotantes con el %f en el printf, pero me genera un error cuando intento cargarlo en una variable en el processing con el comando:

Código: [Seleccionar]
float[] val = float(split (a0, "\n"));

No tengo el proyecto ahora, pero en un rato lo conecto y te digo cual es el error

Desconectado marito

  • PIC16
  • ***
  • Mensajes: 217
Re: programa para graficar señales [pedido]
« Respuesta #24 en: 06 de Junio de 2012, 09:14:08 »
Hola Gera!

El problema estaba en processing. Use el sketch que me pasaste con algunas modificaciones y comenzó a trabajar muy bien!

Una de las modificaciones que hice fue la velocidad de comunicación, uso 56000 mbps. Lo que me pasa ahora es que se pone lenta el refresco de las señales que me manda el PIC. Puede ser que se "atore" a esta velocidad de transmisión?

Desconectado gera

  • Colaborador
  • PIC24H
  • *****
  • Mensajes: 2188
Re: programa para graficar señales [pedido]
« Respuesta #25 en: 06 de Junio de 2012, 12:50:36 »
Yo estoy utilizando 115200 baudios en la comunicacion y me funciona bastante bien. No creo que haya un cuello de botella ahi, es una velocidad bastante alta como para que la puedas percibir visualmente. Tal vez tenes tu pc muy cargada y lo que se esta demorando es el refresco de la imagen.
Si te queres sacar la duda, podes poner en el micro un timer que mida el tiempo entre una trasmision y la otra, y asi vas a ver que tan rapida es la trasmision.
Saludos!

"conozco dos cosas infinitas: el universo y la estupidez humana. Y no estoy muy seguro del primero." A.Einstein

Desconectado marito

  • PIC16
  • ***
  • Mensajes: 217
Re: programa para graficar señales [pedido]
« Respuesta #26 en: 06 de Junio de 2012, 12:58:46 »
Lo que estoy midiendo actualmente es el tiempo de ciclo de ejecución de programa, dentro de cual tengo la transmisión de datos, que es de 5mseg aproximadamente.


Voy a probar cerrar todos los programas y ejecutar solo el processing. Lo que me resulta raro es que un terminal común recibe los datos a gran velocidad, pero puede ser que al estar graficando necesite mayor cantidad de recursos

Desconectado marito

  • PIC16
  • ***
  • Mensajes: 217
Re: programa para graficar señales [pedido]
« Respuesta #27 en: 07 de Junio de 2012, 23:21:15 »
Gera probe con comunicación a 56000 y 9600 baudios y me da el siguiente error luego de unos segundos:

Código: [Seleccionar]
Exception in thread "Animation Thread" java.lang.ArrayIndexOutOfBoundsException: 1
at Medicion_angulo.drawGraph(Medicion_angulo.java:53)
at Medicion_angulo.draw(Medicion_angulo.java:46)
at processing.core.PApplet.handleDraw(Unknown Source)
at processing.core.PApplet.run(Unknown Source)
at java.lang.Thread.run(Thread.java:662)

 Desde el PIC mando las mediciones del acelerómetro y giróscopo en flotante, expresado en grados.

Código: [Seleccionar]
printf("%f, %f, \r",anggrad,angacelgrad); //imprimo datos por puerto serie
El sketch lo modifique y quedo como lo pongo a continuación:

Código: [Seleccionar]
import processing.serial.*;
Serial myPort;  // The serial port

float acc_angle=0;
float gyro_angle=0;
float angle=0;

void setup()
{
  size(650,300);
  println(Serial.list());
  myPort = new Serial(this, Serial.list()[0], 56000);
  myPort.write("m\r");
}


void draw ()
{
  while (myPort.available() > 0)
  {
    String recibido = myPort.readStringUntil('\n');
    if (recibido != null)
    {
      float[] val = float(split(recibido,","));
      drawGraph(val);
    }
  }
}

void drawGraph(float[] val)
{
 acc_angle = ((val[1])*PI/180.0);
 gyro_angle = ((val[0])*PI/180.0);
 
 
  stroke(0);
  background(255);
  rectMode(CENTER);
  textSize(14);
 
  pushMatrix();
    fill(255,100,100);
    translate(100, 200);
    text("acc angle = " + degrees(acc_angle) + "º" ,-90,-100);
    rotate(acc_angle);
    rect(0, 0, 100, 30);
  popMatrix();

  pushMatrix();
    fill(100,255,100);
    translate(300, 200);
    text("gyro angle = " + degrees(gyro_angle) + "º" ,-90,-100);
    rotate(gyro_angle);
    rect(0, 0, 100, 30);
  popMatrix();

  pushMatrix();
    fill(100,100,255);
    translate(500, 200);
    text("filtered angle = " + degrees(angle) + "º" ,-90,-100);
    rotate(angle);
    rect(0, 0, 100, 30);
  popMatrix();


Se te ocurre alguna idea de cual puede ser el problema?

Saludos!!!

Desconectado gera

  • Colaborador
  • PIC24H
  • *****
  • Mensajes: 2188
Re: programa para graficar señales [pedido]
« Respuesta #28 en: 07 de Junio de 2012, 23:46:00 »
Código: [Seleccionar]
printf("%f, %f, \r",anggrad,angacelgrad); //imprimo datos por puerto serie

Ese printf deberia ser:
Código: [Seleccionar]
printf("%f,%f,\n",anggrad,angacelgrad);
Sin los espacios y con un salto de linea (\n) al final. Tambien fijate que antes de empezar a graficar, processing envia una letra 'm' por el puerto serie. Eso sirve para sincronizar el pic con processing. Dejas al pic esperando a q reciba esa 'm' antes de empezar a mandar los datos. Por ej:

Código: [Seleccionar]
while(getc() != 'm');
...resto del codigo

"conozco dos cosas infinitas: el universo y la estupidez humana. Y no estoy muy seguro del primero." A.Einstein