TODOPIC

Mecatrónica => UAV => Mensaje iniciado por: elgarbe en 05 de Enero de 2014, 11:51:14

Título: Magnetometro - UAV's
Publicado por: elgarbe en 05 de Enero de 2014, 11:51:14
Los magnetómetro son sensores que miden la el campo magnético (en gauss) al cual son sometidos. Si bien existen sensores que miden en uno o dos ejes, hoy en día son muy comunes los giróscopos que miden en los tres ejes. Son lo suficientemente sensibles como para medir el campo magnético de la tierra y por ellos son excelentes para obtener el ángulo que hemos rotado nuestro UAV respecto del Norte (Yaw angle).
En mi caso estoy trabajando y mostraré resultados aquí del hmc5883l de Honeywell. Lo tengo montado una plaquita que compre en dx.com.
Esta (http://www51.honeywell.com/aero/common/documents/myaerospacecatalog-documents/Defense_Brochures-documents/HMC5883L_3-Axis_Digital_Compass_IC.pdf) es la página del datasheet.

Como todos los sensores que hemos visto hasta ahora, los magnetómetros tienen 4 parámetros fundamentales. EL/los rangos de operacion, la sensibilidad, el Output data rate y el Zero level offset.
El magnetómetro es un sensor "lento" ya que puede trabajar a apenas 75-160 Hz dependiendo si está configurado como medicion continua o como medicion única.
La sensibilidad del sensor puede elegirse entre +-0.88 Ga hasta +-8.1Ga. Por defecto el sensor está en +-1.3Ga. Dependiendo del rango elegido tendremos una sensibilidad determinada. Por ejemplo, en +-1.3Ga la sensibilidad es de 0.92 mG/LSB.

Debido a que queremos usar el magnetómetro para medir el débil campo magnetico de la tierra debemos tener en cuenta ciertos puntos importantes.
El magnetómetro es de 3 ejes, normalmente mediremos el campo magnético con los ejes X e Y.
El vector flujo magnético terreste no es paralelo a la tierra, está levemente apuntando hacia abajo y el ángulo con respecto a la superficie terrestre depende de la latitud en donde nos encontremos.
El vector flujo no apunta directamente al Norte, esta levemente desplazado. Dependiendo de donde nos encontremos será el ángulo de desviacion.
El campo magnético de la tierra es muy debil y por lo tanto es suceptible de ser modificado o perturbado por varios factores. Debido a esto se hace necesaria la calibracion denominada soft iron y la denominada hard iron.

Hay muchas notas de aplicacion y material en la web sobre este tema, ya que es bastante complejo. Nosotros haremos algunas simplificaciones al principio para poder avanzar y luego veremos como mejorar los resultados obtenidos.
Algunos links interesantes:
http://www.varesano.net/blog/fabio/first-steps-hmc5843-arduino-verify-accuracy-its-results - Fabio Versano ha escrito mucha informacion sobre sensores (gyro, accel, mag), IMU, navegacion, etc.
http://memsense.com/support

Calibración:
http://www.bot-thoughts.com/2011/04/quick-and-dirty-compass-calibration-in.html
http://forum.arduino.cc/index.php/topic,38104.0.html
https://forum.sparkfun.com/viewtopic.php?f=14&t=18510

Bueno, vamos a tratar de poner en marcha el magnetómetro directamente para ir viendo los problemas que encontremos para ir resolviéndolos.

Saludos!
Título: Re: Magnetometro - UAV's
Publicado por: elgarbe en 05 de Enero de 2014, 11:53:43
Leyendo los registros Identification

Bueno, veamos un pequeño ejemplo para leer el registro Identification Register A, B y C y verificar el funcionamiento de la comunicacion:

Lamentablemente para muchos, mi placa de desarrollo es la LPCXpresso, por lo que el código que propongo es para ella. Es C, por lo que se podrá modificar facilmente a cualquier otro uC.

Bueno, este es mi archivo HMC5883L.h
Código: [Seleccionar]
/*
 * HMC5883L.h
 *
 *  Created on: 04/12/2013
 *      Author: elgarbe
 */

#ifndef HMC5883L_H_
#define HMC5883L_H_

#include "i2c.h"
#include <math.h>

extern volatile uint8_t I2CMasterBuffer[I2C_PORT_NUM][BUFSIZE];
extern volatile uint8_t I2CSlaveBuffer[I2C_PORT_NUM][BUFSIZE];
extern volatile uint32_t I2CReadLength[I2C_PORT_NUM];
extern volatile uint32_t I2CWriteLength[I2C_PORT_NUM];

#define HMC5883L_READ_ADDR       0x3D
#define HMC5883L_WRITE_ADDR      0x3C

#define Config_Reg_A             0x00
#define Config_Reg_B             0x01
#define Mode_Reg                 0x02
#define X_MSB_Reg                0x03
#define X_LSB_Reg                0x04
#define Z_MSB_Reg                0x05
#define Z_LSB_Reg                0x06
#define Y_MSB_Reg                0x07
#define Y_LSB_Reg                0x08
#define Status_Reg               0x09
#define ID_Reg_A                 0x0A
#define ID_Reg_B                 0x0B
#define ID_Reg_C                 0x0C

#define PORT_USED 1

short make_word(unsigned char HB, unsigned char LB);
void HMC5883L_init();
char HMC5883L_read(unsigned char reg);
char HMC5883L_write(unsigned char reg_address, unsigned char value);



short make_word(unsigned char HB, unsigned char LB){
   return ((HB << 8) | LB);
}

void HMC5883L_init(){

   HMC5883L_write(Config_Reg_A, 0x70); //Configuramos el magnetómetro
   HMC5883L_write(Config_Reg_B, 0xA0);
   HMC5883L_write(Mode_Reg, 0x00);
}


char HMC5883L_read(unsigned char reg){
I2CWriteLength[PORT_USED] = 2;
I2CReadLength[PORT_USED] = 1;
I2CMasterBuffer[PORT_USED][0] = HMC5883L_WRITE_ADDR;
I2CMasterBuffer[PORT_USED][1] = reg;
I2CMasterBuffer[PORT_USED][2] = HMC5883L_READ_ADDR;

I2CEngine( PORT_USED );

return(I2CSlaveBuffer[PORT_USED][0]);
}


char HMC5883L_write(unsigned char reg_address, unsigned char value){

I2CWriteLength[PORT_USED] = 3;
I2CReadLength[PORT_USED] = 0;
I2CMasterBuffer[PORT_USED][0] = HMC5883L_WRITE_ADDR;
I2CMasterBuffer[PORT_USED][1] = reg_address;
I2CMasterBuffer[PORT_USED][2] = value;

return(I2CEngine( PORT_USED ));
}

#endif /* HMC5883L_H_ */


Bueno, como ven al principio estan todos los define con las direcciones de cada registro. Luego tengo las funciones típicas necesarias para usar el Mag en esta aplicacion.

Mi main.c es este:

Código: [Seleccionar]
#ifdef __USE_CMSIS
#include "LPC17xx.h"
#endif

#include <cr_section_macros.h>
#include <NXP/crp.h>
#include "i2c.h"
#include "HMC5883l.h"
#include "uart2.h"


/*******************************************************************************
**   Main Function  main()
*******************************************************************************/
int main (void){
unsigned char dev_id;

I2C1Init(); /* initialize I2c1 */
HMC5883L_init();
UART2_Init(115200); // Inicializo el UART a 115200

UART2_PrintString ("\rMagnetómetro HMC5883L\r\n");
UART2_PrintString ("======== elgarbe ==========\r\n");

dev_id=HMC5883L_read(ID_Reg_A);
UART2_PrintString("\r\nEl registro Identificatio Register A contiene: ");
uart2_printUint32(dev_id, 10);

dev_id=HMC5883L_read(ID_Reg_B);
UART2_PrintString("\r\nEl registro Identificatio Register B contiene: ");
uart2_printUint32(dev_id, 10);

dev_id=HMC5883L_read(ID_Reg_C);
UART2_PrintString("\r\nEl registro Identificatio Register C contiene: ");
uart2_printUint32(dev_id, 10);

while ( 1 ){
}
}

Simplemente se inicializa el I2C, luego se inicializa el Mag. Para ello solo hace falta escribir 2 registros. el Config_Reg_A y el Config_Reg_B

Finalmente inicializamos la UART, escribimos un mensaje para luego leer los registros de identificación y mostrar su valor.

El terminal obtengo la siguiente salida

(http://imagizer.imageshack.us/v2/800x600q90/542/4isd.jpg) (https://imageshack.com/i/f24isdj)

Saludos!
Título: Re: Magnetometro - UAV's
Publicado por: elgarbe en 26 de Enero de 2014, 22:03:06
Leyendo los datos RAW

Bueno, ahora que ya estamos "hablando" con el Mag, debemos poder leer la informacion de los Gauss que está midiendo.
Para ello simplemente voy a agregar una funcion que me permita leer los 6 registros de datos y unir X_L con X_H para obtener el dato completo del eje X (al igual que con los otros ejes) ya que la lectura es de 16 bits con signo (complemento a 2).

Código: [Seleccionar]
char HMC5883L_read_data(){

uint32_t result=0;
I2CWriteLength[PORT_USED] = 2;
I2CReadLength[PORT_USED] = 6;
I2CMasterBuffer[PORT_USED][0] = HMC5883L_WRITE_ADDR;
I2CMasterBuffer[PORT_USED][1] = X_MSB_Reg;
I2CMasterBuffer[PORT_USED][2] = HMC5883L_READ_ADDR;

result=I2CEngine( PORT_USED );

X_axis = make_word(I2CSlaveBuffer[PORT_USED][0], I2CSlaveBuffer[PORT_USED][1]);
Z_axis = make_word(I2CSlaveBuffer[PORT_USED][2], I2CSlaveBuffer[PORT_USED][3]);
Y_axis = make_word(I2CSlaveBuffer[PORT_USED][4], I2CSlaveBuffer[PORT_USED][5]);

return(result);
}

Como se puede ver se leen 6 registros, a partir de la direccion X_MSB_Reg. Luego se arma el dato combinando de a dos los registros leídos para armar un short con signo (16 bits).

En el main tenemos:
Código: [Seleccionar]
#ifdef __USE_CMSIS
#include "LPC17xx.h"
#endif

#include <cr_section_macros.h>
#include <NXP/crp.h>

signed short mag_X, mag_Y, mag_Z;

volatile uint32_t msTicks; /* counts 1ms timeTicks */
// ****************
// systick_delay - creates a delay of the appropriate number of Systicks (happens every 1 ms)
__INLINE static void delay_ms (uint32_t delayTicks) {
  uint32_t currentTicks;

  currentTicks = msTicks; // read current tick counter
  // Now loop until required number of ticks passes.
  while ((msTicks - currentTicks) < delayTicks);
}


#include "i2c.h"
#include "HMC5883l.h"
#include "uart2.h"

void SysTick_Handler(void) {
msTicks++; /* increment counter necessary in Delay() */
}

/*******************************************************************************
**   Main Function  main()
*******************************************************************************/
int main (void)
{
//Configuro el SysTick para que interrumpa cada 1mseg
if (SysTick_Config(SystemCoreClock / 1000)) {
while (1);  // Capture error
}

I2C1Init(); // Inicializamos el bus I2C
HMC5883L_init(); // Inicializamos el Magnetómetro
UART2_Init(115200); // Inicializamos el UART a 115200

UART2_PrintString ("\rMagnetómetro HMC5883L\r\n");
UART2_PrintString ("======== elgarbe ==========\r\n");

UART2_PrintString ("\r\nRAW X\tRAW Y\tRAW Z\r\n");

while ( 1 ){
HMC5883L_read_data();

uart2_printInt32(mag_X, 10);
UART2_Sendchar('\t');
uart2_printInt32(mag_Y, 10);
UART2_Sendchar('\t');
uart2_printInt32(mag_Z, 10);
UART2_Sendchar('\r');
UART2_Sendchar('\n');

delay_ms(500);
}

}

Como se puede ver, tenemos 3 variables globales signed short para almacenar los datos del Mag.
Aquí estamos haciendo uso del SysTick timer de los Cortex M3. Está configurado para que interrumpa cada 1 mseg, lo usamos para crear la funcion delay_ms.
Como antes, inicializamos el bus I2C, el magnetómetro y la UART. Luego llamamos a la funcion read_data del HMC5883L e imprimimos en la UART el resultado.

Esta es una imagen de nuestra terminal:

(http://imagizer.imageshack.us/v2/800x600q90/163/rfh2.jpg) (https://imageshack.com/i/4jrfh2j)

Bien, esos son los datos crudos del mag, no son gauss ni grados de desvío del polo Norte. Podemos ver que cuando giré el sensor los datos en el eje X y Y cambiaron un poco, mientras que los del eje Z son bastantes estables.

Bien, entonces el siguiente paso lógico sería convertir los datos RAW en Gauss.

Eso quedará para la próxima entrega.
Saludos!
Título: Re: Magnetometro - UAV's
Publicado por: jonathanPIC888 en 27 de Enero de 2014, 16:33:37
Para las personas que están utilizando microcontroladores PIC y CCS, tenemos la siguiente librería para el magnetómetro HMC5883L:

Encabezado de la librería.


Código: C
  1. // CCS library compilation [2014]
  2. // Driver para el magnetometro HMC5883L.
  3. // Programador: Moyano Jonathan
  4. // Compilador: CCS v4.140
  5. // Version de la libreria: v1.0 Revision: 0.1
  6. // Fecha de modificacion: Enero de 2014.
  7.  
  8. // Incluimos librerias utilizadas.
  9. #include <math.h>
  10.  
  11. #define HMC5883L_READ_ADDR       0x3D
  12. #define HMC5883L_WRITE_ADDR      0x3C
  13.                            
  14. #define ConfiguratioRegisterA    0x00
  15. #define ConfiguratioRegisterB    0x01
  16. #define ModeRegister             0x02
  17. #define X_MSB_Reg                0x03
  18. #define X_LSB_Reg                0x04
  19. #define Z_MSB_Reg                0x05
  20. #define Z_LSB_Reg                0x06
  21. #define Y_MSB_Reg                0x07
  22. #define Y_LSB_Reg                0x08
  23. #define Status_Reg               0x09
  24. #define ID_Reg_A                 0x0A              
  25. #define ID_Reg_B                 0x0B
  26. #define ID_Reg_C                 0x0C
  27.  
  28. #define Measurement_Continuous   0x00
  29. #define Measurement_SingleShot   0x01
  30. #define Measurement_Idle         0x03
  31.        
  32. #define declination_angle      5.818 // Determinar segun el lugar donde vivas.
  33. // Determinar la declinacion:  http: //magnetic-declination.com/
  34. // Conversion de unidades:     http: //www.wolframalpha.com/
  35.                                    
  36. // Definimos los pines utilizados para la comunicacion (POR DEFECTO).
  37. #define _SDA PIN_B0
  38. #define _SCL PIN_B1
  39.  
  40. // Configuramos el puerto utilizado para la comunicacion I2C a 400Khz.
  41. #use i2c(Master,Fast, SDA=_SDA, SCL=_SCL)  
  42.                                              
  43. // Variables auxiliares.                                    
  44. register signed long X_axis = 0x00;
  45. register signed long Y_axis = 0x00;                                  
  46. register signed long Z_axis = 0x00;
  47.  
  48. // Factor de escala.
  49. float m_scale = 1.0;
  50.  
  51. // Escribe un registro del HMC5838L.
  52. void HMC5883L_write(unsigned char reg_address, unsigned char value);
  53. // Lee un registro del HMC5838L.
  54. unsigned char HMC5883L_read(unsigned char reg);
  55. // Escalamos los valores.
  56. void HMC5883L_set_scale(float gauss);
  57. // Setea el modo de medicion.
  58. void SetMeasurementMode(unsigned char mode);
  59. // Inicializa el magnetometro HMC5883L.
  60. void HMC5883L_init();  
  61. // Lee los datos sin escalar.
  62. void HMC5883L_read_data_raw();
  63. // Escalamos los datos.
  64. void HMC5883L_ReadScaledAxis();
  65. // Conversion de los datos a grados.
  66. float HMC5883L_headingDegree();


Aquí hay que ver un punto importante, el ángulo de declinación, que cambia según el punto geográfico donde estemos ubicados. Para esto tenemos 2 páginas web que nos
ayudarán mucho:

Ángulo de declinación (http://http: //magnetic-declination.com/)

Acá tenemos que determinar donde estamos:

(http://i822.photobucket.com/albums/zz150/MoyanoJonathan/angulodeclinacion_zps9af00f56.png)

Luego con el dato obtenido, tenemos que convertirlo a miliradianes. Para ello tenemos la siguiente página:

Conversión de unidades (http://www.wolframalpha.com/)

(http://i822.photobucket.com/albums/zz150/MoyanoJonathan/conversion1_zps1ecf9608.png)

Ahora la página nos dá el valor final que tenemos que incluir en nuestro encabezado:

(http://i822.photobucket.com/albums/zz150/MoyanoJonathan/conversion2_zps89277b89.png)

Luego en el archivo .h cambiamos según localidad:

Código: C
  1. #define declination_angle      5.818 // Acorde a la localidad donde vivas.

El archivo .C con el desarrollo de funciones:

Código: C
  1. // CCS library compilation [2014]
  2. // Driver para el magnetómetro HMC5883L.
  3. // Programador: Moyano Jonathan
  4. // Compilador: CCS v4.140
  5. // Versión de la librería: v1.0 Revisión: 0.1
  6. // Fecha de modificación: Enero de 2014.
  7.  
  8. // Incluimos librerías utilizadas.
  9. #include <HMC5883L.h>
  10. // Desarrollo de las funciones de usuario.
  11.  
  12. void HMC5883L_write(unsigned char reg_address, unsigned char value){
  13.  
  14.    i2c_start();                     // Inicializa comunicación I2C, condición de start.
  15.    i2c_write(HMC5883L_WRITE_ADDR);  // Envíamos la dirección del dispositivo + comando para escritura.
  16.    i2c_write(reg_address);          // Indicamos que registro será escrito.
  17.    i2c_write(value);                // Enviamos el nuevo valor al registro.
  18.    I2c_Stop();                      // Condición de stop.
  19.  
  20. }
  21.  
  22. unsigned char HMC5883L_read(unsigned char reg){
  23.  
  24. unsigned char val = 0x00;           // Variable auxiliar.
  25.    
  26.    i2c_start();                     // Inicializa comunicación I2C, condición de start.
  27.    i2c_write(HMC5883L_WRITE_ADDR);  // Envíamos la dirección del dispositivo + comando para escritura.
  28.    i2c_write(reg);                  // Indicamos que registro será leído.
  29.    i2c_start();                     // Reiniciamos la comunicación.
  30.    i2c_write(HMC5883L_READ_ADDR);   // Envíamos la dirección del dispositivo + comando para lectura.
  31.    val = i2c_read(0);               // Leemos el registro.        
  32.    i2c_stop();                      // Condición de stop.
  33.    return(val);                     // Retornamos con el valor leído.
  34. }
  35.  
  36. void HMC5883L_set_scale(float gauss)                      
  37. {
  38.    unsigned char value = 0x05;    
  39.    
  40.     if(gauss == 0.88){value = 0x00; m_scale = 0.73;}  
  41.     else if(gauss == 1.3){value = 0x01; m_scale = 0.92;}  
  42.     else if(gauss == 1.9){value = 0x02; m_scale = 1.22;}  
  43.     else if(gauss == 2.5){value = 0x03; m_scale = 1.52;}  
  44.     else if(gauss == 4.0){value = 0x04; m_scale = 2.27;}
  45.     else if(gauss == 4.7){value = 0x05; m_scale = 2.56;}  
  46.     else if(gauss == 5.6){value = 0x06; m_scale = 3.03;}    
  47.     else if(gauss == 8.1){value = 0x07; m_scale = 4.35;}        
  48.                                                
  49.    value <<= 5;
  50.    HMC5883L_write(ConfiguratioRegisterB, value);
  51. }
  52.  
  53. void SetMeasurementMode(unsigned char mode){
  54.  
  55. HMC5883L_write(ModeRegister,mode);
  56.  
  57. }
  58.  
  59. void HMC5883L_init(){
  60.  
  61.    HMC5883L_write(ConfiguratioRegisterA, 0x70);
  62.    HMC5883L_write(ConfiguratioRegisterB, 0xA0);
  63.    SetMeasurementMode(Measurement_Continuous);
  64.    HMC5883L_set_scale(1.3);
  65. }
  66.  
  67. void HMC5883L_read_data_raw(){
  68.  
  69. unsigned char lsb = 0;
  70. unsigned char msb = 0;
  71.    
  72.    i2c_start();                     // Inicializa comunicación I2C, condición de start.
  73.    i2c_Write(HMC5883L_WRITE_ADDR);  // Envíamos la dirección del dispositivo + comando para escritura.
  74.    i2c_Write(X_MSB_Reg);            // Accedemos a la parte alta del registro que contiene los datos en el eje X.
  75.    i2c_Start();                     // Reiniciamos la comunicación.
  76.    i2c_Write(HMC5883L_READ_ADDR);   // Envíamos la dirección del dispositivo + comando para lectura.
  77.    
  78.    msb = i2c_Read();                // Lee MSB del registro que contiene los datos en el eje X.
  79.    lsb = i2c_Read();                // Lee LSB del registro que contiene los datos en el eje X.
  80.    X_axis = make16(msb,lsb);        // Guarda los datos en una variable auxiliar.
  81.                            
  82.    msb = I2C_Read();                // Lee MSB del registro que contiene los datos en el eje Z.
  83.    lsb = I2C_Read();                // Lee LSB del registro que contiene los datos en el eje Z.
  84.    Z_axis = make16(msb,lsb);        // Guarda los datos en una variable auxiliar.
  85.                    
  86.    msb = I2C_Read();                // Lee MSB del registro que contiene los datos en el eje Y.
  87.    lsb = I2C_Read(0);               // Lee LSB del registro que contiene los datos en el eje Y.
  88.    Y_axis = make16(msb,lsb);        // Guarda los datos en una variable auxiliar.    
  89.                        
  90.    i2c_stop();                      // Condición de stop.
  91. }
  92.  
  93. void HMC5883L_ReadScaledAxis(){
  94.  
  95.    X_axis *= m_scale;
  96.    Z_axis *= m_scale;                            
  97.    Y_Axis *= m_scale;
  98. }
  99.  
  100. float HMC5883L_headingDegree(){
  101.  
  102. register float heading = 0.00;
  103.    
  104.    HMC5883L_read_data_raw();
  105.    HMC5883L_ReadScaledAxis();
  106.    heading = atan2(Y_axis, X_axis);
  107.    float _declinationAngle = declination_angle/1000.0;
  108.     heading += _declinationAngle;    
  109.                  
  110.     if(heading < 0.0)
  111.     {
  112.       heading += (2.0 * PI);
  113.     }
  114.    
  115.     if(heading > (2.0 * PI))                
  116.     {                            
  117.       heading -= (2.0 * PI);
  118.     }                    
  119.                    
  120.    heading *= (180.0 / PI);
  121.                    
  122.    return heading;
  123. }

La función float HMC5883L_headingDegree(), obtiene el rumbo o dirección en grados.

Para ver el funcionamiento del mag, tenemos el siguiente main:

Código: C
  1. // Programa: Prueba del sensor HMC5883L.
  2. // Programador: Moyano Jonathan.
  3. // Fecha: Enero de 2014.
  4. // Versión: v1.0
  5. // Revisión: r0.1
  6. /////////////////////////////////////////
  7.  
  8. // Incluimos plantilla.
  9. #include <Plantilla_UconnectME28.h>  // Drivers de periféricos.
  10.  
  11.  
  12.  
  13. void main () {
  14.  
  15. // Inicializamos el sensor.
  16. HMC5883L_init();
  17.  
  18.    while(true){
  19.  
  20.       // Leemos los datos sin escalar.
  21.       HMC5883L_read_data_raw();
  22.        fprintf(DEBUG,"xRaw:%lu yRaw:%lu zRaw:%lu\r\n",X_axis,Y_axis,Z_axis);
  23.       // Leemos los datos escalados.
  24.       HMC5883L_ReadScaledAxis();
  25.        fprintf(DEBUG,"xScaled:%lu yScaled:%lu zScaled:%lu\r\n",X_axis,Y_axis,Z_axis);
  26.       // Leemos el ángulo en grados.
  27.        fprintf(DEBUG,"Heading:%03.2f\r\n\r\n",HMC5883L_headingDegree());
  28.       // 250 ms entre lecturas.
  29.       delay_ms(250);
  30.  
  31.    }  
  32.    
  33.     }

Para más información, podemos recurrir a la siguiente página (puede ser un poco lenta la carga):  http://www.loveelectronics.co.uk/Tutorials/8/hmc5883l-tutorial-and-arduino-library (http://www.loveelectronics.co.uk/Tutorials/8/hmc5883l-tutorial-and-arduino-library)

El tutorial es para arduino, pero sirve para cualquier plataforma.

Todavía falta implementar la compensación de inclinación, utilizando un acelerómetro, pero lo dejaremos para más adelante. Mientras tanto, pueden ver la implementación
con arduino en el siguiente enlace: http://www.loveelectronics.co.uk/Tutorials/13/tilt-compensated-compass-arduino-tutorial (http://www.loveelectronics.co.uk/Tutorials/13/tilt-compensated-compass-arduino-tutorial)

Saludos !  :-/

Título: Re: Magnetometro - UAV's
Publicado por: elgarbe en 27 de Enero de 2014, 17:18:59
Muy, pero muy bueno Jonathan!!!!!

Que bueno que compartas con nosotros tus avances! Desde ya que voy a tomar muchos de tus criterios de programacion para mejorar mis librerías!!!

Saludos y estamos en contacto
Título: Re: Magnetometro - UAV's
Publicado por: elgarbe en 27 de Enero de 2014, 21:24:53
Obteniendo Gauss - Verificando calibracion

Bueno, llegó el momento de que este bichito empiece a dar informacion que sirva para algo!

Como ya hemos comentado y como bien nos ha mostrado jonathan, el magnetómetro mide el campo magnético de la tierra. En mi caso estoy usando la medicion con los eje X e Y paralelos a la tierra. Por lo tanto, con ellos realizaré la medicion.
Así como los gyro y accel tenían probelmas de zero rate level y había que hacer una calibracion más o menos complicada, los magnetómetro tienen lo suyo.
El campo magnético de la tierra es muy débil y por lo tanto suceptible a muchas perturbaciones. un imán cercano, una mesa metálica, un motor eléctrico funcionando cerca, son todas fuentes de perturbaciones. Por lo tanto es de esperarce que para un correcto funcionamiento se deba calibrar el magnetómetro en el dispositivo final en el que será usado.

Bueno, veamos el código.
Mi HMC5883L.h es el siguiente:

Código: [Seleccionar]
#ifndef HMC5883L_H_
#define HMC5883L_H_

#include "i2c.h"
#include <math.h>

extern volatile uint8_t I2CMasterBuffer[I2C_PORT_NUM][BUFSIZE];
extern volatile uint8_t I2CSlaveBuffer[I2C_PORT_NUM][BUFSIZE];
extern volatile uint32_t I2CReadLength[I2C_PORT_NUM];
extern volatile uint32_t I2CWriteLength[I2C_PORT_NUM];

#define HMC5883L_READ_ADDR       0x3D
#define HMC5883L_WRITE_ADDR      0x3C

#define Config_Reg_A             0x00
#define Config_Reg_B             0x01
#define Mode_Reg                 0x02
#define X_MSB_Reg                0x03
#define X_LSB_Reg                0x04
#define Z_MSB_Reg                0x05
#define Z_LSB_Reg                0x06
#define Y_MSB_Reg                0x07
#define Y_LSB_Reg                0x08
#define Status_Reg               0x09
#define ID_Reg_A                 0x0A
#define ID_Reg_B                 0x0B
#define ID_Reg_C                 0x0C

#define PORT_USED 1

short make_word(unsigned char HB, unsigned char LB);
void HMC5883L_init();
char HMC5883L_read(unsigned char reg);
char HMC5883L_write(unsigned char reg_address, unsigned char value);
char HMC5883L_read_data();


short make_word(unsigned char HB, unsigned char LB){
   return ((HB << 8) | LB);
}

void HMC5883L_init(){

   HMC5883L_write(Config_Reg_A, 0b00010000); //Configuramos el magnetómetro sin promedio de muestras
   HMC5883L_write(Config_Reg_B, 0b00100000); //15Hz de ODR, Normal mode, 1.3Ga de rango
   HMC5883L_write(Mode_Reg, 0x00); //Modo de sensado continuo
}


char HMC5883L_read(unsigned char reg){
I2CWriteLength[PORT_USED] = 2;
I2CReadLength[PORT_USED] = 1;
I2CMasterBuffer[PORT_USED][0] = HMC5883L_WRITE_ADDR;
I2CMasterBuffer[PORT_USED][1] = reg;
I2CMasterBuffer[PORT_USED][2] = HMC5883L_READ_ADDR;

I2CEngine( PORT_USED );

return(I2CSlaveBuffer[PORT_USED][0]);
}


char HMC5883L_write(unsigned char reg_address, unsigned char value){

I2CWriteLength[PORT_USED] = 3;
I2CReadLength[PORT_USED] = 0;
I2CMasterBuffer[PORT_USED][0] = HMC5883L_WRITE_ADDR;
I2CMasterBuffer[PORT_USED][1] = reg_address;
I2CMasterBuffer[PORT_USED][2] = value;

return(I2CEngine( PORT_USED ));
}

char HMC5883L_read_data(){

uint32_t result=0;
I2CWriteLength[PORT_USED] = 2;
I2CReadLength[PORT_USED] = 6;
I2CMasterBuffer[PORT_USED][0] = HMC5883L_WRITE_ADDR;
I2CMasterBuffer[PORT_USED][1] = X_MSB_Reg;
I2CMasterBuffer[PORT_USED][2] = HMC5883L_READ_ADDR;

result=I2CEngine( PORT_USED );

mag_X = make_word(I2CSlaveBuffer[PORT_USED][0], I2CSlaveBuffer[PORT_USED][1]);
mag_Z = make_word(I2CSlaveBuffer[PORT_USED][2], I2CSlaveBuffer[PORT_USED][3]);
mag_Y = make_word(I2CSlaveBuffer[PORT_USED][4], I2CSlaveBuffer[PORT_USED][5]);

return(result);
}
#endif /* HMC5883L_H_ */

Como se puede ver en la inicializacion solo configuramos el sensor para que haga lecturas continuas, sin promediarlas, un ODR de 15Hz y un rango de +-1.3Gauss. Con este rango, la sensibilidad queda determinada en 0.92mgauss/LSB.

En esta aplicacion lo que estoy buscando es mostrar gráficamente los datos que devuelve el magnetómetro con y sin perturvaciones. Es por ello que no haeré aún el cálculo del ángulo respecto del Norte.

Mi main.c es el siguiente:

Código: [Seleccionar]
#ifdef __USE_CMSIS
#include "LPC17xx.h"
#endif

#include <cr_section_macros.h>
#include <NXP/crp.h>

signed short mag_X = 0;
signed short mag_Y = 0;
signed short mag_Z = 0;

volatile uint32_t msTicks; /* counts 1ms timeTicks */
// ****************
// systick_delay - creates a delay of the appropriate number of Systicks (happens every 1 ms)
__INLINE static void delay_ms (uint32_t delayTicks) {
  uint32_t currentTicks;

  currentTicks = msTicks; // read current tick counter
  // Now loop until required number of ticks passes.
  while ((msTicks - currentTicks) < delayTicks);
}


#include "i2c.h"
#include "HMC5883l.h"
#include "uart2.h"

void SysTick_Handler(void) {
msTicks++; /* increment counter necessary in Delay() */
}

/*******************************************************************************
**   Main Function  main()
*******************************************************************************/
int main (void)
{
float gaus_X=0.0;
float gaus_Y=0.0;
float gaus_Z=0.0;

//Configuro el SysTick para que interrumpa cada 1mseg
if (SysTick_Config(SystemCoreClock / 1000)) {
while (1);  // Capture error
}

I2C1Init(); // Inicializamos el bus I2C
HMC5883L_init(); // Inicializamos el Magnetómetro
UART2_Init(115200); // Inicializamos el UART a 115200

UART2_PrintString ("\rMagnetómetro HMC5883L\r\n");
UART2_PrintString ("======== elgarbe ==========\r\n");

UART2_PrintString ("\r\nGauss X\tGauss Y\tGauss Z\r\n");

while ( 1 ){
HMC5883L_read_data();

gaus_X = (float)mag_X * 0.92/1000;
gaus_Y = (float)mag_Y * 0.92/1000;
gaus_Z = (float)mag_Z * 0.92/1000;

uart2_printDouble(gaus_X, 4);
UART2_Sendchar('\t');
uart2_printDouble(gaus_Y, 4);
UART2_Sendchar('\t');
uart2_printDouble(gaus_Z, 4);
UART2_Sendchar('\r');
UART2_Sendchar('\n');

delay_ms(500);
}

}

Como se puede observar simplemente leemos los datos RAW y los multiplicamos por la sensibilidad. La divicion por 1000 es para obtener el resultado en gauss. Según la wikipedia el campo magnético de la tierra (https://es.wikipedia.org/wiki/Campo_magnetico_de_la_Tierra) ronda los 0.25 a 0.65 gauss.

Veamos que obtenemos nosotros:

(http://imagizer.imageshack.us/v2/800x600q90/202/zb23.jpg) (https://imageshack.com/i/5mzb23j)

como se puede ver estamos en concordancia con lo esperado.

Bueno, ahora biene lo importante, antes de poder leer el ángulo de desviacion respecto al Norte magnético (o al norte geográfico si hacemos la correccion que explicó jonathan en 2 post más arriba) debemos asegurarnos que el offset y la sensibilidad de cada eje sea correcto. Para ello vamos a loguear datos cada xx mseg del eje X y del eje Y. Luego haremos un gráfico X vs Y en excel para ver la figura que se forma. La teoría dice que debería ser un círculo centrado en el origen... veamos que obtengo:

(http://imagizer.imageshack.us/v2/800x600q90/585/7v3s.jpg) (https://imageshack.com/i/g97v3sj)

Bueno, como puede observarse tenemos un círculo casi perfecto, el tema es que lejos está de estar centrado en el origen.
Bueno, empecemos a estudiar los datos. Lo primero que debemos obtener es el máximo y el mínimo en cada eje, en mi caso obtengo:

Maximo X   0,3551   Minimo X   0,011
Maximo Y   -0,1592   Minimo Y   -0,495

con estos datos podemos obtener el rango en cada eje:

Rango X   0,3441
Rango Y   0,3358

Como podemos ver son muy parecidos, por lo que no parece requerir ajuste de sensivilidad. Incluso la pequeña diferencia puede deberse a alguna inclinacion involuntaria del sensor mientras lo giraba...

Bueno, con estos datos calculo el offset con el que hay que ajustar cada eje para obtener el círculo centrado en el origen:

Offset X   0,18305
Offset Y   -0,3271

restando dicho valor a cada lectura del magnetómetro obtendremos la lectura corregida.

Veamos ahora el resultado aplicando ese offset a los datos previamente logueados:

(http://imagizer.imageshack.us/v2/800x600q90/546/paqo.jpg) (https://imageshack.com/i/f6paqoj)

Bueno, ahora sí! un círculo casi perfecto!!!!

Este algoritmo de calibración debería implementarse en el uC y ejecutarlo al montarlo en el dispositivo final. Esos valores de offset deberían ser definitivos.
Pueden ver en el primer post la llamada calibracion para hard iron y para soft iron.

Bueno, con el magnetómetro corregido podemos obtener el tan deseado ángulo respecto al norte. Para ello utilizaremos el trabajo de Jonathan y sus librerías.

Saludos!
Título: Re: Magnetometro - UAV's
Publicado por: elgarbe en 27 de Enero de 2014, 22:37:12
Obteniendo el Heading (° respecto del norte)

Bueno, ahora si estamos en condiciones de probar lo que nos propone Jonathan, el cálculo del ángulo de giro respecto del Norte, o Heading.
Como les venía comentando, en mi caso no necesito una medicion absoluta (posicion respecto del Norte geográfico) sino que necesito una medicion relatuva, por lo menos por ahora. Es por ello que voy a ovbiar por ahora el dato declination del lugar.

Sin mucho que agregar a lo que escribio jonathan, este es mi main.c:

Código: [Seleccionar]
#ifdef __USE_CMSIS
#include "LPC17xx.h"
#endif

#include <cr_section_macros.h>
#include <NXP/crp.h>

signed short mag_X = 0;
signed short mag_Y = 0;
signed short mag_Z = 0;
#define PI  3.141592653589793238462643383279502884197f

volatile uint32_t msTicks; /* counts 1ms timeTicks */
// ****************
// systick_delay - creates a delay of the appropriate number of Systicks (happens every 1 ms)
__INLINE static void delay_ms (uint32_t delayTicks) {
  uint32_t currentTicks;

  currentTicks = msTicks; // read current tick counter
  // Now loop until required number of ticks passes.
  while ((msTicks - currentTicks) < delayTicks);
}


#include "i2c.h"
#include "HMC5883l.h"
#include "uart2.h"

void SysTick_Handler(void) {
msTicks++; /* increment counter necessary in Delay() */
}

/*******************************************************************************
**   Main Function  main()
*******************************************************************************/
int main (void)
{
float gaus_X=0.0;
float gaus_Y=0.0;
float gaus_Z=0.0;
float heading=0.0;

//Configuro el SysTick para que interrumpa cada 1mseg
if (SysTick_Config(SystemCoreClock / 1000)) {
while (1);  // Capture error
}

I2C1Init(); // Inicializamos el bus I2C
HMC5883L_init(); // Inicializamos el Magnetómetro
UART2_Init(115200); // Inicializamos el UART a 115200

UART2_PrintString ("\rMagnetómetro HMC5883L\r\n");
UART2_PrintString ("======== elgarbe ==========\r\n");

UART2_PrintString ("\r\nGauss X\tGauss Y\tHeading\r\n");

while ( 1 ){
HMC5883L_read_data();

gaus_X = (float)mag_X * 0.92/1000 - 0.18305; //Resto el offset obtenido en el Excel
gaus_Y = (float)mag_Y * 0.92/1000 + 0.3271;
gaus_Z = (float)mag_Z * 0.92/1000;

heading = atan2(gaus_Y, gaus_X); //Calculo el ángulo respecto al Norte Magnético
if(heading < 0.0){ //Si el valor es negativo
heading += (2.0 * PI); //sumamos 2*Pi para que no queden cortes en transiciones
} // de 179° a -180°
if(heading > (2.0 * PI)){ // Por si el valor es mayor a 2 PI
heading -= (2.0 * PI);
}
heading *= (180.0 / PI); //Paso a °

uart2_printDouble(gaus_X, 4);
UART2_Sendchar('\t');
uart2_printDouble(gaus_Y, 4);
UART2_Sendchar('\t');
uart2_printDouble(heading, 4);
UART2_Sendchar('\r');
UART2_Sendchar('\n');

delay_ms(500);
}

}

La gran diferencia es que ahora ajustamos con el Offset calculado en el post anterior para poder obtener lecturas correctas.
Bien, con esa correccion y agregando el cálculo del heading obtengo lo siguiente en el terminal:

Código: [Seleccionar]

Magnetómetro HMC5883L
======== elgarbe ==========

Gauss X Gauss Y Heading
0.1629 0.0318 11.0411
0.1675 0.0088 3.0011
0.1629 -0.0170 354.0482
0.1583 -0.0418 345.1989
0.1564 -0.0455 343.7822
0.1518 -0.0602 338.3654
0.1417 -0.0777 331.2639
0.1316 -0.0933 324.6510
0.1104 -0.1127 314.4273
0.1003 -0.1292 307.8212
0.0773 -0.1393 299.0228
0.0470 -0.1513 287.2397
0.0304 -0.1559 281.0305
0.0065 -0.1614 272.2953
-0.0202 -0.1596 262.7822
-0.0395 -0.1577 255.9313
-0.0763 -0.1412 241.6018
-0.1067 -0.1265 229.8468
-0.1288 -0.1035 218.7801
-0.1444 -0.0777 208.2825
-0.1610 -0.0519 197.8833
-0.1610 -0.0372 193.0193
-0.1711 -0.0115 183.8321
-0.1711 0.0180 174.0008
-0.1674 0.0391 166.8408
-0.1545 0.0778 153.2824
-0.1380 0.1054 142.6278
-0.1233 0.1201 135.7416
-0.1067 0.1348 128.3564
-0.0966 0.1422 124.1847
-0.0782 0.1569 116.4832
-0.0542 0.1679 107.9021
-0.0276 0.1735 99.0311
-0.0037 0.1753 91.1928
0.0120 0.1716 86.0036
0.0267 0.1689 81.0115
0.0543 0.1633 71.6082
0.0764 0.1523 63.3628
0.0985 0.1376 54.4076
0.1169 0.1201 45.7809
0.1288 0.1045 39.0364
0.1463 0.0805 28.8317
0.1555 0.0640 22.3633
0.1638 0.0327 11.2904

Podemos observar un giro completo.  :-/

Bueno, queda pendiente algunas de las cosas más importantes, incluir la rutina de calibracion en el código (requiere de interaccion del usuari ocon el sistema), estudiar la calibracion necesaria cuando el sensor está cerca de objetos que perturben el campo de la tierra y finalmente la compensación por inclinacion...

Saludos!
Título: Re: Magnetometro - UAV's
Publicado por: jonathanPIC888 en 27 de Enero de 2014, 22:44:28
En este semana voy a modificar las librerías para poder añadir tu rutina de calibración y voy a corroborar para ver si obtengo resultados similares.
Título: Re: Magnetometro - UAV's
Publicado por: PCCM en 28 de Enero de 2014, 18:29:58
Recuerda que la calibración debe ser en 3D, ya que los UAV no realizan movimientos solo en 2D.
La calibración cuando esta cerca de objetos que perturban el campo magnético de la tierra se hace la misma calibración pero con aquellos elementos.
En cuanto la compensación por inclinación si no me convence como escribí en el otro post. Asi se use los ángulos de inclinación para corregirlos, no se obtiene buenos resultados, llega a los 40 grados(ejem. cabeceo) aprox y a partir de ahí tengo una desviación de hasta 20 grados en azimut(cuando llega a 90 grados en cabeceo).

Espero que alguien me confirme o diga que si funciona para todos los angulos y como lo hizo. :mrgreen:
Ya que en lo que he leído sobre la corrección de inclinación no he visto que hagan pruebas para ángulos pronunciados.

Saludos.
Título: Re: Magnetometro - UAV's
Publicado por: elgarbe en 28 de Enero de 2014, 19:27:01
Recuerda que la calibración debe ser en 3D, ya que los UAV no realizan movimientos solo en 2D.
La calibración cuando esta cerca de objetos que perturban el campo magnético de la tierra se hace la misma calibración pero con aquellos elementos.
En cuanto la compensación por inclinación si no me convence como escribí en el otro post. Asi se use los ángulos de inclinación para corregirlos, no se obtiene buenos resultados, llega a los 40 grados(ejem. cabeceo) aprox y a partir de ahí tengo una desviación de hasta 20 grados en azimut(cuando llega a 90 grados en cabeceo).

Espero que alguien me confirme o diga que si funciona para todos los angulos y como lo hizo. :mrgreen:
Ya que en lo que he leído sobre la corrección de inclinación no he visto que hagan pruebas para ángulos pronunciados.

Saludos.

El tema me parece que pasa por que en los UAV "caseros" el magnetómetro es un "accesorio". Se utiliza, generalmente, para ajustar la deriva del giróscopo, como ya bien sabes. Entonces no se esfuerzan demasiado en hacerlo funcionar en cualquier ángulo. yo no he visto tampoco aplicaciones funcionando bien con grandes inclinaciones.... aparte si queremos hilar fino, ni siquiera el acelerómetro sirve para medir ángulos cercanos a los 90°. Pasando los 45° pierde la linealidad y la gran sensivilidad que tiene la funcion seno con ángulos pequeños...
En tu caso necesitás si o sí presicion en cualquier ángulo?.

Saludos!
Título: Re: Magnetometro - UAV's
Publicado por: PCCM en 30 de Enero de 2014, 21:50:19
Para las inclinaciones pronunciadas hay varias aplicaciones en videojuegos por ejemplo. y el magnetómetro creo que es muy importante(u otro sensor que sense el azimut) no lo veo que alguien lo utilice como accesorio sobre todo en UAV caseros. Lo que quiero mas que precisión es robustes, ya que para que un dato de azimut varié mucho ante una inclinación no me da confiabilidad de aplicar otros algoritmos y que se comporten bien.(y en otras pruebas variaba hasta mas, llegaba a mas de 40 grados, analizándolo con los datos guardados ya que yo veia 20 grados a puro ojo nomas.)

Bueno escribo para responder a mi pregunta, el cual estaba convencido de que se puede hacer un buen funcionamiento del magnetómetro para inclinaciones pronunciadas después de ver el siguiente video.


Desde el minuto 2:30 me respondió a mi pregunta.

Lo que sucedía era de que la calibración lo realizaba en otra hoja, pero lo raro es que el programa no realizaba la corrección de la calibración(es bien raro). Bueno lo que hice es hacer la calibración en la hoja principal.

Obteniendo buenos resultados.

(http://imageshack.com/a/img191/7646/pf30.png)

Como se puede observar en la leyenda para angulos de cabeceo de [-75.6 hasta 79]  y banqueo de[-74.7 hasta 84] el azimut permanecía en promedio de 158 grados. bueno con un rango de 15 grados, pero eso se debe a al movimiento en azimut que realizaba mientras cabeceaba o banqueaba. hice otra prueba mas precisa y se desviaba promedio 5 grados, a veces se desviaba solo 1 grados. esas variaciones creo se deben al calculo de la actitud ya que el filtro kalman que aplico aún no es robusto y tiene una pequeña latencia en la estimación del angulo. ya que parece que aún no tuneo bien la covarianza del error en el proceso. o bien aplicar el kalman extendido, lo cual aún voy a probar.  

Aunque en el video dice que las inclinaciones le afectan minimamente no dice cuanto es "minimamente". pero por ahora me conformo con la respuesta.
En la parte derecha por si alguien quiere analizar estan las lecturas del magnetometro, todo analizado en las 548 muestras.

Saludos.
Título: Re: Magnetometro - UAV's
Publicado por: elgarbe en 31 de Enero de 2014, 21:08:24
Hola!

Como yo lo veo, usando la matriz DCM, el sensor principal es el giróscopo. Ese es el sensor que debe funcionar lo mejor posible y el que hay que calibrar lo mejor posible. Luego, el resto son "accesorios", el acelerómetro permitirá corregir uno de los vectores de la DCM y el magnetómetro otro vector. Incluso el MatrixPilot que es más para aviones utiliza el GPS para el heading y corregir el yaw. Son sensores que se usan para "corregir" el drift del gyro. El peso que se le da a la correccion ronda el 1% por lo que es muy poco lo que corrige.
Incluso imaginate que si el gyro deriva muy poco, con corregir una vez cada tanto alcanzaría. uno podría ovbiar la medicion del magnetómetro cuando el UAV este inclinado cierto ángulo si quisiera...
Lo qu eplanteo es el caso extremo, si se puede calibrar bien el acelerómetro y el magnetómetro todo funcionará mejor, pero no lo veo tan crítico. Ahora estoy por agregar el acelerómetro a la DCM para ver que resultados tenemos...

Saludos
Título: Re: Magnetometro - UAV's
Publicado por: chavaroon en 20 de Octubre de 2014, 14:48:33
Oye elgarbe, ¿al obtener los datos en Excel (Que no sé cómo lo haces), lo haces moviendo de algún modo al Magnetómetro? ¿O dejas al sensor estático? Tengo esa curiosidad, pues estoy tratando de calibrar el mío. Para calibrarlo en realidad solo hago múltiples mediciones y obtengo los mínimos y máximos de los ejes X y Y. Tomo esa diferencia en los ejes y se la resto a las nuevas mediciones. Pero no logro obtener buenos resultados. Supongo pues que es en la calibración.
Título: Re: Magnetometro - UAV's
Publicado por: elgarbe en 20 de Octubre de 2014, 15:18:26
Oye elgarbe, ¿al obtener los datos en Excel (Que no sé cómo lo haces), lo haces moviendo de algún modo al Magnetómetro? ¿O dejas al sensor estático? Tengo esa curiosidad, pues estoy tratando de calibrar el mío. Para calibrarlo en realidad solo hago múltiples mediciones y obtengo los mínimos y máximos de los ejes X y Y. Tomo esa diferencia en los ejes y se la resto a las nuevas mediciones. Pero no logro obtener buenos resultados. Supongo pues que es en la calibración.

para calibrar tenes que rotar 360º el sensor en un solo eje y almacenar lo obtenido, luego en otro eje y luego en otro. Luego se grafica en excel y se obtiene el offset en cada eje.
No debe haber objetos metálicos serca ni campos magneticos ni electricos potentes.

sds.
Título: Re: Magnetometro - UAV's
Publicado por: chavaroon en 14 de Enero de 2015, 22:57:58
Oye elgarbe, ¿al obtener los datos en Excel (Que no sé cómo lo haces), lo haces moviendo de algún modo al Magnetómetro? ¿O dejas al sensor estático? Tengo esa curiosidad, pues estoy tratando de calibrar el mío. Para calibrarlo en realidad solo hago múltiples mediciones y obtengo los mínimos y máximos de los ejes X y Y. Tomo esa diferencia en los ejes y se la resto a las nuevas mediciones. Pero no logro obtener buenos resultados. Supongo pues que es en la calibración.

para calibrar tenes que rotar 360º el sensor en un solo eje y almacenar lo obtenido, luego en otro eje y luego en otro. Luego se grafica en excel y se obtiene el offset en cada eje.
No debe haber objetos metálicos serca ni campos magneticos ni electricos potentes.

sds.

Gracias por el dato, oye y aprovechando ¿Cómo haces las gráficas X y Y? ¿Qué software utilizas o qué onda?
Ah, por cierto. En tu opinión: ¿Qué objetos afectan la calibración del Magnetómetro? Porque tengo en mi escritorio Bocinas, Celulares, un RadioControl, una Batería y motores DC y Brushless Jaja
Título: Re: Magnetometro - UAV's
Publicado por: chavaroon en 25 de Marzo de 2015, 14:46:48
Oye elgarbe, ¿al obtener los datos en Excel (Que no sé cómo lo haces), lo haces moviendo de algún modo al Magnetómetro? ¿O dejas al sensor estático? Tengo esa curiosidad, pues estoy tratando de calibrar el mío. Para calibrarlo en realidad solo hago múltiples mediciones y obtengo los mínimos y máximos de los ejes X y Y. Tomo esa diferencia en los ejes y se la resto a las nuevas mediciones. Pero no logro obtener buenos resultados. Supongo pues que es en la calibración.

para calibrar tenes que rotar 360º el sensor en un solo eje y almacenar lo obtenido, luego en otro eje y luego en otro. Luego se grafica en excel y se obtiene el offset en cada eje.
No debe haber objetos metálicos serca ni campos magneticos ni electricos potentes.

sds.

Gracias por el dato, oye y aprovechando ¿Cómo haces las gráficas X y Y? ¿Qué software utilizas o qué onda?
Ah, por cierto. En tu opinión: ¿Qué objetos afectan la calibración del Magnetómetro? Porque tengo en mi escritorio Bocinas, Celulares, un RadioControl, una Batería y motores DC y Brushless Jaja


Ya supe como graficar en tiempo real directamente en Excel, si alguien está interesado haga clic en la liga siguiente: https://www.parallax.com/downloads/plx-daq
Es bastante sencillo de integrar.

Ahora, sobre el magnetómetro. ¿Es correcto decir que esta calibración que se hizo (ajustar el offset para centrar el origen en 0,0 ) es el llamado soft-iron?
Título: Re: Magnetometro - UAV's
Publicado por: cyberian en 22 de Junio de 2015, 03:21:08
Hola, quería saber si voy bien orientado, soy nuevo en esto de las IMU. Tengo una IMU GY-87, ya logré acceder a los datos RAW del acelerómetro, giróscopo que están en la IMU6050 y mediante baypass configurar el magentómetro HMC5883L, que una vez configurado, accedo a él mediante la IMU6050 en modo master. Todo por ahora en un PIC18F45K20, después tengo que pasar a un dsPIC y un Cortex M4 de Texas. La idea es hacer fusión sensorial sin usar el módulo DMP de la IMU6050 (según el datasheet, tiene soporte integrado completo de fusión de datos de acelerómetro, giróscopo y acelerómetro conectado al puerto I2C auxiliar) pero según estuve investigando, es mentira, no hay soporte completo, la fuente de esto es la página de I2Cdev, donde ellos aseguran que esto lo han dicho los empleados de IvenSense. Usando Kalman, quiero fusionar el acelerómetro y giróscopo para obtener roll, pitch y sus derivadas (velocidades angulares) y mediante fusión del giróscopo y magnetómetro, obtener el yaw y su derivada.
Por ahora logré importar todos los datos en modo RAW a Wolfram Mathematica 10.1 en tiempo real (mediante RS232 y Dynamic), ahí en tiempo real aplico Kalman para fusión de sensores y visualización. Una vez que todo funcione, esto se resolverá dentro del dsPIC y el Cortex M4 de texas (TM4C123GH6PM).
Leí que hay que obtener el offset del magnetómetro en 3D, y se me ocurrió utilizar los datos obtenidos en tiempo real, almacenarlos en una lista y realizar un ajuste implícito no lineal para estimar un elipsoide y obtener los semiejes (que representarían en gauss el campo magnético terrestre) y el centro, que representaría el offset en los tres ejes. Unos puntos se me salieron del elipsoide porque pasé muy cerca de los cables de la fuente, y se notó el desvío, ahora estoy poniendo cablés más largos para hacer nuevas pruebas, y ajustar un elipsoide que incluya rotaciones (la ecuación de la superficie cuádrica completa en 3D y así el ajuste sea mejor).
Con respecto a cómo tomé los datos, es simple, moviendo libremente el magnetómetro todo lo que se pueda, sin restricciones -salvo pasarlo cerca de los cables- (porque una corriente genera campos que causan desvíos en las mediciones). Miestras más giros completos en toda dirección y sentido se dé, mejor para el ajuste. Saludos a todos.
Título: Re: Magnetometro - UAV's
Publicado por: elgarbe en 22 de Junio de 2015, 09:21:32
vas perfecto y estoy muy interesado en tu trabajo. Si quieres abrir un post nuevo aquí para mostrar losavances serían muy bien venidos!!
Cuando pases al TM4C contá conmigo para trabajar en el código.

Yo estoy metido en el proyecto MatrixPilot, para portar ese autopilot a un STM32F4 y como consejo te puedo decir que busques trabajar con sensores SPI. Yo tengo conectado el MPU6000 con SPI y usando DMA el micro ni se entera de la lectura de los datos. Podes tener un refresh rate grandísimo.

Saludos!
Título: Re: Magnetometro - UAV's
Publicado por: cyberian en 22 de Junio de 2015, 09:36:37
Muchas gracias!!!, sí, con la comunicación I2C estoy muy limitado en cuanto a la fracuencia de muestreo, no puedo superar por mucho los 200 Hz, pero esta IMU ya viene así. Acabo de comprar esta IMU, http://www.aliexpress.com/snapshot/6736509118.html?orderId=67829496724044
estoy esperando a que llegue.
No sé si con esa frecuencia de muestreo que estoy logrando pueda hacer una caracterización del sistema para obtener la función de transferencia con MATLAB. Unos compañeros están teniendo problemas para estabilizar el cuadcóptero, pero están unsando el módulo DMP para fusionar los datos, yo quiero hacerlo con Kalman y poder comparar.
¿Qué opinión tienen respecto a la MPU-9250 9-eje actitud + giroscopio + acelerador + magnetómetro? es SPI, por eso la compré, tarda 39 días en llegar a Argentina, mientras tanto experimento con la que tengo, para adquirir experiencia.
Hace poco terminé el curso que dictó la Universidad de Texas en Austin sobre Sistemas Embebidos, ahí conocí la TIVA launchpad, compré algunas en TI y pedí varias muestras del CORTEX, así que tengo para entretenerme.
Ahora que nombrás los DMA, voy a intentar usarlos en el dsPIC -ya que en el curso no vimos el uso del DMA en el Cortex-, que también tengo en todos los colores, jajaja. Por ahora estoy pasando el código al dsPIC33FJ128MC804 que trabaja a 40MIP, pero tengo otros más fuertes que llegan a 70MIPS, pero tengo que hacer las placas. Saludos y gracias por la orientación. Apenas tenga la fusión hecha en Mathematica, comparto el archivo, además necesito estimar las matrices de covarianza de los sensores, para que Kalman funcione mejor. Mathematica hace el trabajo, ya lo hice para el acelerómetro y giróscopo, ahora trabajaré sobre el magnetómetro. Abrazos!!!
Título: Re: Magnetometro - UAV's
Publicado por: elgarbe en 22 de Junio de 2015, 10:50:00
Muchas gracias!!!, sí, con la comunicación I2C estoy muy limitado en cuanto a la fracuencia de muestreo, no puedo superar por mucho los 200 Hz, pero esta IMU ya viene así. Acabo de comprar esta IMU, http://www.aliexpress.com/snapshot/6736509118.html?orderId=67829496724044
estoy esperando a que llegue.
No sé si con esa frecuencia de muestreo que estoy logrando pueda hacer una caracterización del sistema para obtener la función de transferencia con MATLAB. Unos compañeros están teniendo problemas para estabilizar el cuadcóptero, pero están unsando el módulo DMP para fusionar los datos, yo quiero hacerlo con Kalman y poder comparar.
¿Qué opinión tienen respecto a la MPU-9250 9-eje actitud + giroscopio + acelerador + magnetómetro? es SPI, por eso la compré, tarda 39 días en llegar a Argentina, mientras tanto experimento con la que tengo, para adquirir experiencia.
Hace poco terminé el curso que dictó la Universidad de Texas en Austin sobre Sistemas Embebidos, ahí conocí la TIVA launchpad, compré algunas en TI y pedí varias muestras del CORTEX, así que tengo para entretenerme.
Ahora que nombrás los DMA, voy a intentar usarlos en el dsPIC -ya que en el curso no vimos el uso del DMA en el Cortex-, que también tengo en todos los colores, jajaja. Por ahora estoy pasando el código al dsPIC33FJ128MC804 que trabaja a 40MIP, pero tengo otros más fuertes que llegan a 70MIPS, pero tengo que hacer las placas. Saludos y gracias por la orientación. Apenas tenga la fusión hecha en Mathematica, comparto el archivo, además necesito estimar las matrices de covarianza de los sensores, para que Kalman funcione mejor. Mathematica hace el trabajo, ya lo hice para el acelerómetro y giróscopo, ahora trabajaré sobre el magnetómetro. Abrazos!!!

Tengo 2 de esas imu, me llegaron hace unas semanas y no tuve tiempo de probarlas. Tambien tengo 2 MPU9250 (el integradito suelto).
El curso de texas lo inicie dos veces, una el año pasado y otra este año y nunca me pude hacer tiempo para terminarlo. Tambien tengo la lunch pad y varias muestras del 123  :D
Mi consejo es, deja de lado el dsPIC. A no ser que necesites usarlo para otra cosa, pasate directamente a ARM, el que quieras, TI, ST, NXP, pero alejate cuanto antes de microchip!!!  :D
Yo estoy trabajando con una Núcleo de ST, la STM32F411, por USD10 tenes un M4F a 100MHz. Le hice un shield con el MPU6000, sd card, entrada para Rx, 6 salidas para servos o ESC y otras cositas más:
(https://c4.staticflickr.com/8/7699/16658689784_102fd5e6e2_z.jpg) (https://flic.kr/p/ro596o)

Si te interesa: http://www.todopic.com.ar/foros/index.php?topic=41978.0

Por cierto, a 200Hz tenes que poder estabilizar el quad. Ahora, a 1KHz como leo yo... podes mejorar bastante!

Me interesa la parte de levantar los datos en mathematica con 232. Podrías explicar un poco eso?

saludos!
Título: Re: Magnetometro - UAV's
Publicado por: cyberian en 22 de Junio de 2015, 11:30:18
Sí, mi idea de comenzar a migrar de Microchip, en la Universidad de la Matanza dieron un curso de Sistemas Embebidos (uEA2015), fui desde Neuquén y fue desastroso el curso. Usamos la STM32 Discovery. Estoy con el dsPIC porque lo sé usar, y como tiene 2 módulos QEI, lo usé para hacer mis péndulos invertidos, y ahora que aprendí Kalman, estoy rehaciéndolos aplicando lo nuevo aprendido  :D. El proyecto de fusión de datos es para una materia de la facu, Introducción a los Vehículos Inteligentes, estuvo muy buena, y sumada a los tres cursos https://www.edx.org/course/autonomous-mobile-robots-ethx-amrx-0 https://www.edx.org/course/flight-vehicle-aerodynamics-mitx-16-110x https://www.edx.org/course/autonomous-navigation-flying-robots-tumx-autonavx-0 estoy muy motivado,  :-/
Te dejo un archivo que hice con Mathematica, para levantar los datos RAW enviados sólo por el acelerómetro, aplicarle Kalman en tiempo real y graficar en tiempo real el vector aceleración, con y sín filtro de Kalman. El algoritmo de Kalman recursivo lo hice yo, no usé las funciones build-in de Mathematica, pero ya las he comparado y dan exactamente lo mismo. Los datos los envío en formato little-endian, uno tras otro, sólo 6 datos enteros sin signo provenientes del acelerómetro. Después los convierto a enteros con signo de 16 bits en Mathematica, ahí está la función.
Saludos
Título: Re: Magnetometro - UAV's
Publicado por: cyberian en 22 de Junio de 2015, 11:59:46
Listo, acá dejo el archivo de Mathematica para estimar el offset 3D del magnetómetro -esta vez tomé datos lejos de campos magnéticos-  :P. Dejo una comparativa antes y después de aplicar el ajuste. El color de los ejes es como la convención de programas CAD (Red-X, Green-Y, Blue-Z). Saludos.
Título: Re: Magnetometro - UAV's
Publicado por: Ranculche en 18 de Agosto de 2015, 16:03:14
Hola a todos. Escribo para preguntarles si alguno utilizo este magnetómetro como detector de metales? o tiene conocimiento de ello. Estoy probando uno para eso, pero no encuentro mucha info para dicha aplicación. Gracias!

Saludos.-
Título: Re: Magnetometro - UAV's
Publicado por: Alfrematico en 07 de Octubre de 2015, 14:12:37
Saludos

estoy tratando de leer un Magnetometro HMC5883L via i2c usando una targeta C2000 piccolo launchpad de texas instruments, exactamente la C28027

estoy usando Simulink, libreria Embedded Coder, compilando el programa usando CCS 3.3 de texas intruments

he logrado leer los valores en bruto del magnetometro, pero necesito convertirlos a valores que me sirvan para determinar la orientacion de un cuadricoptero...es decir, que me indique el norte magnetico como si fuera una brujula normal, o que vaya de 0 a 360 grados y que se reinicie en 0 cuando llege a 360

mi pregunta es

¿como proceso los datos en bruto del magnetometro?

al leerlos en una GUI no tienen sentido, he leido que multiplican esos valores por la escala escogida, usan una arcotangente, etc...¿podrian explicarme esto mejor?

exactamente cual es el procedimiento matematico para formar angulos de orientacion y poder tomar una referencia?

no importa si es en codigo este procedimiento matematico, solo debo implementarlo en bloques de simulink

PD: ya logre determinar el eje X y Y de inclinacion usando la MPU6050, por si alguien le interesa mi modelo en simulink... converti los valores del acelerometro en grados, siendo 0 grados cuando está horizontal tanto en el eje X como el eje Y.

el magnetometro es para determinar la orientacion o el eje Z del cuadricoptero

Gracias



Título: Re: Magnetometro - UAV's
Publicado por: elgarbe en 07 de Octubre de 2015, 14:44:55
En este (http://www.todopic.com.ar/foros/index.php?topic=41981.msg349884#msg349884) post hago el cálculo del heading. Lo leiste?

la parte del código que hace ese cálculo es esta:

Código: [Seleccionar]
HMC5883L_read_data();

gaus_X = (float)mag_X * 0.92/1000 - 0.18305; //Resto el offset obtenido en el Excel
gaus_Y = (float)mag_Y * 0.92/1000 + 0.3271;
gaus_Z = (float)mag_Z * 0.92/1000;

heading = atan2(gaus_Y, gaus_X); //Calculo el ángulo respecto al Norte Magnético
if(heading < 0.0){ //Si el valor es negativo
heading += (2.0 * PI); //sumamos 2*Pi para que no queden cortes en transiciones
} // de 179° a -180°
if(heading > (2.0 * PI)){ // Por si el valor es mayor a 2 PI
heading -= (2.0 * PI);
}
heading *= (180.0 / PI); //Paso a °

como puedes ver, primero leemos los datos, luego los escalamos según la sensibilidad elegida y a la vez le aplicamos una correccion de offset. Esos coeficientes los obtenemos haciendo una calibracion soft iron. Algo de la teoría de eso esta en lospost anteriores.

Luego, esas componentes son los catetos adyacentes y opuestos de un triángulo rectángulo, cuya hipotenusa es la línea NORTE-SUR. Por eso, se utiliza la tangente del ángulo y para calcular el ángulo se utiliza el arco tangente.
Luego hay unas conversiones ya que, si no me equivoco atan2 devuelve un valor entre -180 y 180º entonces para transformarlo a 0-360º se utilizan las condiciones de abajo.

Para el quad, lo recomendable es usar el eje Z del giróscopo, integrando constantemente la velocidad angular para obtener el ángulo y luego, debido a que el giróscopo tiene drift, pues usar el dato de la brújula para acomodar los datos.

Saludos
Título: Re:Magnetometro - UAV's
Publicado por: Alfrematico en 13 de Octubre de 2015, 12:07:45
Saludos

Gracias por la información de como calcular el heading, acabo de hacer un modelo en simulink y pronto les comentare los resultados. unas preguntas

ustedes calculan en angulo pitch y roll usando una fusion entre en gyroscopio y el acelerometro. Dandole mayor prioridad a lo que mide el giroscopio verdad? (cerca de un 98%)

¿es muy necesaria la fusion sensorial entre los 2 sensores?

el acelerometro por si solo me da unos angulos bastante aproximados a lo real, es bastante sensible a cualquier vibracion. por el momento estoy redondeando el angulo que mide. Esto lo hago debido a que estoy teniendo problemas de memoria en la targeta que estoy utilizando y hacer dicha fusion sensorial me llena la memoria ram de momento.

¿alguien ha utilizado una c2000 de texas instruments?

tiene una memoria flash bastante grande, de momento no se como compilar en ella. xD

igualmente para el eje Z, medirlo con el giroscopio y arreglarlo con el heading del magnetometro es lo que ustedes comentan.

¿que es el offset del magnetometro y como se calcula?

Gracias por la ayuda.
Título: Re:Magnetometro - UAV's
Publicado por: elgarbe en 13 de Octubre de 2015, 13:39:49
ustedes calculan en angulo pitch y roll usando una fusion entre en gyroscopio y el acelerometro. Dandole mayor prioridad a lo que mide el giroscopio verdad? (cerca de un 98%)

Si

¿es muy necesaria la fusion sensorial entre los 2 sensores?

Indispensable. El acelerómetro tiene mucho ruido y el giróscopo tiene deriva. sueltos no sirven para estabilizar.

el acelerometro por si solo me da unos angulos bastante aproximados a lo real, es bastante sensible a cualquier vibracion. por el momento estoy redondeando el angulo que mide. Esto lo hago debido a que estoy teniendo problemas de memoria en la targeta que estoy utilizando y hacer dicha fusion sensorial me llena la memoria ram de momento.

¿alguien ha utilizado una c2000 de texas instruments?

Nop

tiene una memoria flash bastante grande, de momento no se como compilar en ella. xD

igualmente para el eje Z, medirlo con el giroscopio y arreglarlo con el heading del magnetometro es lo que ustedes comentan.

¿que es el offset del magnetometro y como se calcula?

Gracias por la ayuda.

leiste el post completo? http://www.todopic.com.ar/foros/index.php?topic=41981.msg349880#msg349880 (http://www.todopic.com.ar/foros/index.php?topic=41981.msg349880#msg349880)

saludos y ya nos comentas como te va con este tema!
Título: Re:Magnetometro - UAV's
Publicado por: Alfrematico en 18 de Octubre de 2015, 00:05:47
Saludos

gracias a la fusion sensorial del acelerometro y el giroscopio obtengo unos angulos X y Y mas estables... pero aun no logro cuadrar el angulo z usando el magnetometro

he aqui parte mi modelo para procesar los datos del magnetometro HMC5883L en simulink, por ahora trato de obtener el heading y que este vaya de 0 a 360 grados... pero cuando se acerca a 280, baja a 40.

(http://imageshack.com/a/img908/1721/xx91lb.png)
PD: en la imagen se ven los valores del offset con signo negativo, ya corregi esto

- recibe 6 bytes de 8 bits que corresponden a los valores H y L

siendo:
X_H
X_L
Z_H
Z_L
Y_H
Y_L

-fusiona los valores H y L

con esto obtengo los valores raw del magnetometro

a partir de aqui, el bloque arctan hace la siguiente operacion: atan2(B,A)

que seria lo que anteriormente publico elgarbe

                gaus_X = (float)mag_X * 0.92/1000 - 0.18305;   //Resto el offset obtenido en el Excel
      gaus_Y = (float)mag_Y * 0.92/1000 + 0.3271;
      gaus_Z = (float)mag_Z * 0.92/1000;

      heading = atan2(gaus_Y, gaus_X);   //Calculo el ángulo respecto al Norte Magnético
      if(heading < 0.0){               //Si el valor es negativo
         heading += (2.0 * PI);         //sumamos 2*Pi para que no queden cortes en transiciones
      }                           // de 179° a -180°
      if(heading > (2.0 * PI)){         // Por si el valor es mayor a 2 PI
         heading -= (2.0 * PI);
      }
      heading *= (180.0 / PI);         //Paso a °


los if están, si es mayor a 2*pi, si es menor que 0 y si el valor es mayor a 0

me falta algo en el calculo del heading?

para fusionarlo despues con el giroscopio traté de usar este ejemplo, de este saque la fusion sensorial para los angulos X Y y me funcionó muy bien... pero el YAW... no me funciona del todo bien...los valores cambian entre 200-260, a veces ni varia por mucho que gire el sensor

http://jujomaruiit.blogspot.com.co/2015/10/fusion-del-magnetometro-y-giroscopio.html?view=mosaic

posee una formula muy larga para calculo del yaw... a mi no funcionó

 roll = Roll * pi / 180;
pitch = Pitch * pi / 180;
 
sinroll = sin(roll);
cosroll = cos(roll);
sinpitch = sin(pitch);
cospitch = cos(pitch);

menosbfy = (bz * sinroll) - (by * cosroll);
bfx = (bx * cospitch) + (by * (sinpitch * sinroll)) + (bz * (sinpitch * cosroll));


yaw = (atan2(menosbfy , bfx) * 180/pi);

este angulo yaw es el que se mezclaria con el heading....

por ahora ¿el heading está bien?
¿como fusionan el heading del magnetometro con el giroscopio?
Gracias por la ayuda
Título: Re:Magnetometro - UAV's
Publicado por: elgarbe en 19 de Octubre de 2015, 08:28:25
Ten en cuenta que esos Offset del magnetómetro me dio en mi calibracion. Tu tienes que hacer tu calibracion y obtener esos valores para tu caso. En esta misma serie de posts esta explicado como calcular el ofset de calibracion.

Un problema típico es saber si las funciones trigonométricas esperan º sexagesimales o si esperan radianes. A veces los calculos no dan bien por no pasar el parámetro en la unidad correcta.
El if despues del ATAN2 es por la discontinuidad de la funcion en pi radianes:

https://en.wikipedia.org/wiki/File:Atan2-discontinuity.svg

se usa atan2 porque va de 0 a 2pi (0º hasta 360º) (la arctan esta bien definida para -pi/2 y pi/2)

otra cosa que se me ocurre es como tenes configura el HMC, porque dependiendo la sensivilidad elegida es el resultado (y el producto que debes hacer, ese 0.92 que tenes por ahí) que te da. en mi caso la inicializacion es esta:

Código: C
  1. void HMC5883L_init(){
  2.    HMC5883L_write(Config_Reg_A, 0x70);  //Configuramos el magnetómetro
  3.    HMC5883L_write(Config_Reg_B, 0xA0);
  4.    HMC5883L_write(Mode_Reg, 0x00);
  5. }

habría que ver en el datasheet a que corresponde esa configuracion.

Si se me ocurre algo más te aviso.

Saludos
Título: Re:Magnetometro - UAV's
Publicado por: Alfrematico en 20 de Octubre de 2015, 11:28:45
Saludos

Revisando encontré que el heading en mi programa (justo despues del atan2) nunca llega a valores superiores a 2*pi, es posible que tengas razon en lo del tipo de dato que espera ese bloque de atan2

esos 0.92/1000 estaban mal. basandome en un programa de arduino, solo se multiplica los valores raw por la escala elegida, en mi caso seria 0.92 unicamente.

la configuracion es la siguiente:

1.Configuration Register A = 0x10 (configuración por defecto) (¿porque tienes este registro en 0x70?)

con la configuracion  de este registro en 0x10, segun el datasheet tendria:

-Typical Data Output Rate (Hz) = 15 (Default)

-Measurement Mode = Normal measurement configuration (Default). In normal measurement configuration the device follows normal measurement flow. The positive and negative pins of the resistive load are left floating and high impedance.

Configuracion Register B = 0x20 (configuracion por defecto)

Recommended Sensor Field Range = 1.3 gauss
Gain(LSb/Gauss) = 1092 (default)
Digital Resolution (mG/LSb) = 0.92 (esta es la escala por la que multiplico los valores raw)

Mode Register = 0x0 (Medicion continua)

Continuous-Measurement Mode. In continuous-measurement mode, the device continuously performs measurements and places the result in the data register. RDY goes high when new data is placed in all three registers. After a power-on or a write to the mode or configuration register, the first measurement set is available from all three data output registers after a period of 2/fDO and subsequent measurements are available at a frequency of fDO, where fDO is the frequency of data output.

Estoy seguro de que el problema que tengo está en el atan o en la medicion de los valores raw, pues en la salida de ese atan nunca llega a valores superiores a 6.28 (2*pi)

probe este programa en arduino y funciona perfectamente, da el giro de 0 a 360, por este descubri que mi heading nunca llega a valores superiores a 2*pi...creo que nisiquiera tiene calibración, solo agrega un angulo de inclinacion que corresponde a nuestra ubicacion geografica, en mi caso seria -0.105 rad

// Calculate heading when the magnetometer is level, then correct for signs of axis.
  float heading = atan2(scaled.YAxis, scaled.XAxis);

  // Once you have your heading, you must then add your 'Declination Angle', which is the 'Error' of the magnetic field in your location.
  // Find yours here: http://www.magnetic-declination.com/
  // Mine is: 2� 37' W, which is 2.617 Degrees, or (which we need) 0.0456752665 radians, I will use 0.0457
  // If you cannot find your Declination, comment out these two lines, your compass will be slightly off.
  float declinationAngle = 0.009 ;
  heading += declinationAngle;


http://arduikyo.blogspot.nl/2013/08/hmc5883l-compass-arduino-processing.html

Gracias por la ayuda, comentare si logro solucionar esto hoy
Título: Re:Magnetometro - UAV's
Publicado por: Alfrematico en 28 de Enero de 2016, 20:33:10
Saludos

tengo un problema con mi magnetometro HMC5883L de nuevo...

con el calculo del heading=(y/x), me grafica valores de 0 a 360 grados, sin embargo, hay angulos o saltos de angulos

por ejemplo de 0 a 40 grados todo perfecto, pero despues pega un salto brusco a 130 grados y sigue bien hasta otro angulo, en general los saltos son como de 40 grados. en internet no encuentro causas o soluciones a este problema

tengo mi magnetometro montado en mi cuadricoptero

-¿podrian los motores, la IMU, la targeta, etc... causar interferencia en el magnetometro?

leyendo este post me di cuenta de que podia estar haciendo la calibración mal en X y Y, mañana la hago de nuevo y comento

dejo este mensaje por si alguien ha tenido un problema similar... no quisiera saber que mi magnetometro esta defectuoso

Gracias

Edit: el angulo del yaw se determina solo con el magnetometro? o deberé fusionarlo con el acelerometro o giroscopio??

en este tema no he leido mucho, les agradeceria la información
Título: Re:Magnetometro - UAV's
Publicado por: elgarbe en 01 de Febrero de 2016, 06:34:00
Tendrías que poner todo el código para ver si encontramos el error.

La correccion de YAW se utiliza los datos del giróscopo, los cuales se corrigen con el magnetómetro (se le elimina la deriva del giróscopo).

Saludos
Título: Re:Magnetometro - UAV's
Publicado por: Alfrematico en 02 de Febrero de 2016, 03:38:40
Seguro, es un modelo de simulink por lo que es logica de bloques, pero es muy facil de entender

[img=http://s21.postimg.org/e3somkbr7/image.jpg] (http://postimg.org/image/e3somkbr7/)

[img=http://s21.postimg.org/i98n5lfur/image.jpg] (http://postimg.org/image/i98n5lfur/)

si alguien tiene simulink dejo el archivo adjunto

bueno resumiendo, la primera imagen recibo los datos y junto los H con los L, segun ek datasheet, se reciben XH, XL, ZH, HL, YH, YL. con esto corro 8 posiciones y los junto (esto mismo hago con la mpu6050 y me funciona para obtener los datos del acelerometro y el giroscopio) luego multiplico por la escala a la que está configurada que enste caso es 4.35 la mas alta de 8 gaus (intenté con la todas las escalas y obtengo el mismo resultado, se pierden angulos)... despues se le suma el offset:

quizá lo este sacando mal

con la escala mas baja giro mi cuadricoptero en el eje Z y le doy varias vueltas (360 grados) teniendo cuidado de que esté bien horizontal el cuadricoptero, con una gui registro el valor mas pequeño y el mas grande en el eje X y Y

masomenos me dieron algo como Xmin=-400 xmax=100 Ymin=-400 ymax=100 (masomenos, no tengo ahora mismo el offset que hallé)

con eso asumo que a cada eje le debo sumar 150 a lo que mida despues del escalado para que quede xmin=-250 y xmax=250 y lo mismo con el Y, que seria un circulo centrado en el origen verdad????

despues pasan por la funciona atan2(B/A) que seria atan2(Y/X), le resto -0.105 que es la supuesta declinacion magnetica que depende de mi ubicacione geografica, busque mi coordenadas como me aconsejaron aca en este mismo post y da -0.105 radianes

luego pasa por el arreglo que vi en este mismo post

si el resultado es <0

heading=heading+2*pi

si el resultado es >2*pi

heading=heading-2*pi

si el resultado es >0

dejarlo pasar

Agradesco la ayuda

 - Tienes que ingresar para ver archivos adjuntos -