Duda con IMU

Hola:

Estoy haciendo un proyecto en el tiene que interactuar una placa arduino (Diecimilia) y una IMU-5DOF. Estoy un poco perdido, alguien me puede ayudar?. He leido que hay un problema a la hora de implementar un filtro Kalman ya que este necesita un ADC de 12 bits y la placa arduino tiene uno de 10 bits ¿es verdad?, y si es así cómo podría solucionarlo ya que he visto videos en que lo han conseguido.

Gracias

Hola,

Puedes seguir este link para info y código para que veas implementación de Kalman: http://diydrones.com/photo/photo/show?id=705844%3APhoto%3A19728

Salu2 ;)

Igor R.

Gracias Igor por contestar. Es un enlace muy bueno, pero no entiendo los cáculos que hace Jordi en el cual demuestra q[/code]ue no es compatible el Arduino con el giróscopo IDG-300 de la IMU -5DOF de Sparkfun.

Me podrías ayudar, por favor.

Jordi propone comprar otro giróscopo de 300º/seg o poner un convertidor A/D de 12 bits funcionando en paralelo

Hola,

La verdad, que nunca he hecho nada con filtros de kalman. Alguna vez he estado ojeando el tema, y tenía por ahí los links:

Esta última tiene bastante info sobre medir roll, pitch, kalman,…y lo más importante, las mátematicas que hay por detrás…

No sé exactamente lo que quieres hacer, pero puedes utilizar sensores que vayan por SPI ó I2C en vez de analógicos. Verás que mucha aplicaciones usan los acelerómetros de la WII que van por i2c.

Lo que el giroscopo sea de 300º/s ó de menos, depende de tu aplicación. Por ejemplo, en automoción, el yaw rate sensor es de 150º/s ya que para medir el movimiento de yaw de un coche es suficiente. (El ESP de un coche va con ésto).

Para un avión la cosa cambia…

Para un segway o robot balancín tampoco creo que se necesiten altas velocidades… Busca en google por “balancing robot kalman” y verás multitud de webs…

Lo del conversor de 10 bits ó de 12 bits, también me imagino que dependerá de la resolución que necesites, porque si vas a usarlo para integrar la señal y sacar ángulo, pues haz tu mismo los cálculos… Ten en cuenta, que si tienes un giroscopo de +/-300 º/s y usas un ADC de 10 bits(1023 pasos)…

Si miras algo comercial => http://www.oxts.co.uk. Veras que los giros son de 100º/s.

Salu2

Igor R.

Hola Igor:

Gracias por tu ayuda, me estás resolviendo muchas dudas. En cuanto tenga avances te comentaré.

Rigo.

Alguien me puede ayudar a cómo calcular la integral de la velocidad angular (código en arduino). ¿Es normal que me detecte una pequeña velocidad angular cuando la imu está en reposo?

Integral=area.... Haz un google de integral por el método trapecio.... Hay varios métodos de integración númerica, pero ese puede ser un buen inicio... Luego puedes seguir por Runge Kutta. En los link que te deje la última vez habla de ello: http://tom.pycke.be/mav/70/gyroscope-to-roll-pitch-and-yaw

Si es normal que haya +/- 1 º/s en reposo.....

Salu2

Igor R.

Te pongo un ejemplo básico de integral numérica...

Regla del punto medio o regla del rectángulo

En Pseudocódigo la función integral sería: (Imaginemos que cálculas la integral cada 100 Hz.)

Valor_anterior=Valor_nuevo; Valor_nuevo=analogRead;

Integral=Integral+ [(Valor_nuevo+Valor_anterior)/2]*0.01

100 Hz = 0.01 sg

Aunque para algo tan complicado como Kalman, integrales númericas, derivadas númericas,.... Estaría bien que uses algun software tipo Matlab. Primero investigas el algoritmo en alto nivel, y luego bajas a nivel arduino....

Puedes usar el arduino como si fuese una tarjeta de adquisición (coge valores de acelerómetros,gps,... y los manda via serie), con Matlab recoges dichos datos y realizas tu algoritmo. Una vez que tengas todo "fino", ya implementas en Arduino.

Lo digo, para no chocarte lo primero con las matemáticas y te asustes con el proyecto.... Matlab viene con funciones para matrices, rouge kutta, trapezoidal,....

El ejemplo que te he puesto de integral, es lo más básico que hay, pero te aseguro que depende la aplicación funciona. Yo lo uso en calculo de distancia de un coche a través de velocidad y me va bien (a 100 Hz). Pero claro, en mi aplicación no hay grandes aceleraciones...

Animo!! ;)

Igor R.

Muchísimas gracias por tu ayuda Igor. Voy a seguir tu consejo y voy utilizar matlab para verificar y aclarar los datos obtenidos ¿cómo puedo interactuar los dos programas?. Yo he encontrado el siguiente código para comunicarlo con el puerto serie, pero no sé como hacer para obtener una gráfica (plot) de la integral (obtener posición de la velocidad angular).

s = serial('COM7', 'BaudRate', 19200);
fopen(s)
fprintf(s, 'hello arduino!');
end
fclose(s);

Me podrías tb explicar cómo funciona el filtro Kalman. leyendo en los enlaces que me has proporcionado entiendo que es un método para fusionar los ángulos obtenidos mediante el giróscopo y el acelerómetro, pero no lo entiendo muy bien.

Como verás estoy hecho un lío. Me podrías tutorizar, por favor. Llevo 6 meses con este proyecto y no he avanzado nada. Lo que intento es interactuar arduino mediante una imu (5 dof) con algún otro programa como por ejemplo processing. Lo que llevo por ahora es la obtención de la velocidad angular calibrado en grados/seg, así como la acelación, lo obtuve de esta página http://wiki.orbswarm.com/index.php?title=IMU. Luego integré los valores de la velocidad angular para obtener la posición y ahí me he quedado.

Como verás tengo un cacao mental impresionante. Igor, te dejo mi correo por si te sirve de algo. rigo_itt@hotmail.com

Alguien me puede decir cómo hacer una interrupción del timer para hacer una captura del conversor analógico digital conectado al giróscopo en intervalos fijos de tiempo. La necesito para hacer la integración de la señal para averiguar la orientación.

Puedes usar la libreria del Timer 2. http://www.arduino.cc/playground/Main/MsTimer2

Si quieres tener control total, tendrás que configurartelo tu actuando sobre los registros adecuados del micro. Para ello la documentación de atmel + http://www.avrfreaks.net/index.php?name=PNphpBB2&file=viewtopic&t=50106

Salu2

Igor R.

Muchas gracias Igor como siempre sacandome de los apuros. jejeje

Por favor ayuda. Si yo capuro la señal del giróscopo (XRATE) a 1ms (mediante la librería MSTIMER2) y obtengo la velocidad angular en bits (0g->490). Luego lo convierto a grados/seg mediante la siguiente fórmula:

(N-490)/1024 * 3.3V * (1 deg/s)/.002V

Siendo: N = las muestras que voy capturando por el convertidor A/D. 3.3 = A lo que está alimentado el sensor. .002 = la sensibilidad del giróscopo (IDG300).

Después calculo la posición angular mediante una integral por el método del rectangulo, y mi pregunta es:

¿Por qué al girar mi giróscopo 90º obtengo por el monitor de arduino un valor de 907.28º ?¿tiene que ver con el periodo a la que está sometido la integral, ya que es la misma a la que capturo la velociadad angular, 1ms?.

pongo el código para ver mejor cómo he hecho las cosas: Aquí obtengo la velocidad angular y la posición.

void getVelocidadAngularROLL(){
  
    //giroADCROLL = calibracionROLL(analogRead(giroCanal[ROLL]));  //Recuerda que los pines está cambiado
    giroADCROLL = analogRead(giroCanal[ROLL]);  //Recuerda que los pines está cambiado
  
    velocidadAngularROLL[ACTUAL] = ((giroADCROLL - giroCeroROLL)/1024.0)*(3.3/0.002);  //Cálcula velocidad angular del eje ROLL en º/seg
    posicionAngularX[ACTUAL] +=  (velocidadAngularROLL[ACTUAL] + velocidadAngularROLL[ANTERIOR])/2;
    velocidadAngularROLL[ANTERIOR] = velocidadAngularROLL[ACTUAL];
  //Serial.println(analogRead(giroCanal[ROLL]));
    Serial.print("calibracion ");
    Serial.print(giroADCROLL);
        Serial.print("   ");
    Serial.print(giroCeroROLL);
    Serial.print("    ");
    Serial.print("      velociada angular: ");
    Serial.print(velocidadAngularROLL[ACTUAL]);
        Serial.print("      POSICION angular: ");
    Serial.println(posicionAngularX[ACTUAL]);
}

Aquí uso interrupciones para capturar los datos a 1ms

  Serial.begin(BAUDIOS);
  analogReference(EXTERNAL);      //Vref del convertidor 3.3v
  inicializacion();
  initGiro();                     //Inicialización del giróscopo
  
  //Llamada a la rutina de tratamiento de interrupción(ISR)
  MsTimer2::set(mseg, captura); // 1ms de periodo
  MsTimer2::start();            // Inicialización de la interrupción

En este código controlo la rutina de tratamiento de interrupción

void captura() {
  static boolean output = HIGH;
  static int cont;
  
  digitalWrite(13, output);
  output = !output;
  
  cont++;
  
  getVelocidadAngularROLL();
  
  /*if (cont == 100){
     //cont = 0;
     output = false;
     MsTimer2::stop();
     Serial.println("parado");
  }
*/}