void I2C1_IRQHandler( void );
void I2C1Init( void );
uint32_t I2CStart( uint32_t portNum );
uint32_t I2CStop( uint32_t portNum );
uint32_t I2CEngine( uint32_t portNum );
void L3G4200D_write(unsigned char reg_address, unsigned char value){
I2CWriteLength[PORT_USED] = 3;
I2CReadLength[PORT_USED] = 0;
I2CMasterBuffer[PORT_USED][0] = L3G4200D_WRITE_ADDR;
I2CMasterBuffer[PORT_USED][1] = reg_address;
I2CMasterBuffer[PORT_USED][2] = value;
I2CEngine( PORT_USED );
}
Si bien la el uso de I2CEngine no es muy intuitivo, una vez que le he agarrado la mano va como piña.unsigned char L3G4200D_read(unsigned char reg){
// uint32_t result=0;
I2CWriteLength[PORT_USED] = 2;
I2CReadLength[PORT_USED] = 1;
I2CMasterBuffer[PORT_USED][0] = L3G4200D_WRITE_ADDR;
I2CMasterBuffer[PORT_USED][1] = reg;
I2CMasterBuffer[PORT_USED][2] = L3G4200D_READ_ADDR;
I2CEngine( PORT_USED );
return(I2CSlaveBuffer[PORT_USED][0]);
}
Como ven, para leer un registro, primero hay que hacer una operacion de escritura y pasar la direccion que queremos leer. Luego sigue una operacion de lectura. Aquí, I2CEngine hace todo de una.void L3G4200D_init(){
// L3G4200D_write(L3G4200D_CTRL_REG1, 0b00001111); // 100Hz, 12.5 CO, all axis enable
// L3G4200D_write(L3G4200D_CTRL_REG4, 0x20); // 0x00 250 dps, 0x10 500 dps, 0x20 2000dps
L3G4200D_write(L3G4200D_CTRL_REG2, 0b00011001); //
L3G4200D_write(L3G4200D_CTRL_REG3, 0x00); //
L3G4200D_write(L3G4200D_CTRL_REG4, 0b10110000); // 0x00 250 dps, 0x10 500 dps, 0x20 2000dps
L3G4200D_write(L3G4200D_CTRL_REG5, 0b00010011); //
L3G4200D_write(L3G4200D_CTRL_REG1, 0x0F); // 100Hz, 12.5 CO, all axis enable
}
void L3G4200D_read_data(){
// uint32_t result=0;
I2CWriteLength[PORT_USED] = 2;
I2CReadLength[PORT_USED] = 6;
I2CMasterBuffer[PORT_USED][0] = L3G4200D_WRITE_ADDR;
I2CMasterBuffer[PORT_USED][1] = (L3G4200D_DATA_ADDR | (1<<7));
I2CMasterBuffer[PORT_USED][2] = L3G4200D_READ_ADDR;
res_g=I2CEngine( PORT_USED );
gyro_X = make_word2(I2CSlaveBuffer[PORT_USED][1], I2CSlaveBuffer[PORT_USED][0]);
gyro_Y = make_word2(I2CSlaveBuffer[PORT_USED][3], I2CSlaveBuffer[PORT_USED][2]);
gyro_Z = make_word2(I2CSlaveBuffer[PORT_USED][5], I2CSlaveBuffer[PORT_USED][4]);
}
En esta funcion es muy importante el tipo de datos de gyro_X, Y y Z. Deben ser de 16bits con signo. Cada compilador posee un tipo de datos para ellos, en mi caso es signed short. Tambien es importante notar que hay que leer 2 direcciones para formar el dato de cada eje.#ifndef L3G4200D_H_
#define L3G4200D_H_
#include "i2c.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 L3G4200D_READ_ADDR 0xD3
#define L3G4200D_WRITE_ADDR 0xD2
#define L3G4200D_DATA_ADDR 0x28
#define L3G4200D_WHO_AM_I 0x0F
#define L3G4200D_CTRL_REG1 0x20
#define L3G4200D_CTRL_REG2 0x21
#define L3G4200D_CTRL_REG3 0x22
#define L3G4200D_CTRL_REG4 0x23
#define L3G4200D_CTRL_REG5 0x24
#define L3G4200D_REFERENCE 0x25
#define L3G4200D_OUT_TEMP 0x26
#define L3G4200D_STATUS_REG 0x27
#define L3G4200D_OUT_X_L 0x28
#define L3G4200D_OUT_X_H 0x29
#define L3G4200D_OUT_Y_L 0x2A
#define L3G4200D_OUT_Y_H 0x2B
#define L3G4200D_OUT_Z_L 0x2C
#define L3G4200D_OUT_Z_H 0x2D
#define L3G4200D_FIFO_CTRL_REG 0x2E
#define L3G4200D_FIFO_SRC_REG 0x2F
#define L3G4200D_INT1_CFG 0x30
#define L3G4200D_INT1_SRC 0x31
#define L3G4200D_INT1_THS_XH 0x32
#define L3G4200D_INT1_THS_XL 0x33
#define L3G4200D_INT1_THS_YH 0x34
#define L3G4200D_INT1_THS_YL 0x35
#define L3G4200D_INT1_THS_ZH 0x36
#define L3G4200D_INT1_THS_ZL 0x37
#define L3G4200D_INT1_DURATION 0x38
#define PORT_USED 1
void L3G4200D_init();
unsigned char L3G4200D_read(unsigned char reg);
unsigned char L3G4200D_write(unsigned char reg_address, unsigned char value);
void L3G4200D_init(){
L3G4200D_write(L3G4200D_CTRL_REG1, 0b00001111); // 100Hz, 12.5 CO, all axis enable
L3G4200D_write(L3G4200D_CTRL_REG4, 0x20); // 0x00 250 dps, 0x10 500 dps, 0x20 2000dps
}
unsigned char L3G4200D_read(unsigned char reg){
I2CWriteLength[PORT_USED] = 2;
I2CReadLength[PORT_USED] = 1;
I2CMasterBuffer[PORT_USED][0] = L3G4200D_WRITE_ADDR;
I2CMasterBuffer[PORT_USED][1] = reg;
I2CMasterBuffer[PORT_USED][2] = L3G4200D_READ_ADDR;
I2CEngine( PORT_USED );
return(I2CSlaveBuffer[PORT_USED][0]);
}
unsigned char L3G4200D_write(unsigned char reg_address, unsigned char value){
I2CWriteLength[PORT_USED] = 3;
I2CReadLength[PORT_USED] = 0;
I2CMasterBuffer[PORT_USED][0] = L3G4200D_WRITE_ADDR;
I2CMasterBuffer[PORT_USED][1] = reg_address;
I2CMasterBuffer[PORT_USED][2] = value;
return(I2CEngine( PORT_USED ));
}
#endif /* L3G4200D_H_ */
#ifdef __USE_CMSIS
#include "LPC17xx.h"
#endif
#include <cr_section_macros.h>
#include <NXP/crp.h>
#include "uart2.h"
#include <stdio.h>
#include "i2c.h"
#include "L3G4200D.h"
/*******************************************************************************
** Main Function main()
*******************************************************************************/
int main (void){
unsigned char who_am_I;
I2C1Init(); /* initialize I2c1 */
L3G4200D_init();
UART2_Init(56700); // Inicializo el UART a 56700
UART2_PrintString ("\r\nGiroscopo L3G4200D\r\n");
UART2_PrintString ("======== elgarbe ==========\r\n");
who_am_I=L3G4200D_read(L3G4200D_WHO_AM_I);
UART2_PrintString("\r\nEl registro who am I contiene: ");
uart2_printUint32(who_am_I, 10);
while ( 1 ){
}
}
short make_word(unsigned char HB, unsigned char LB){
return ((HB << 8) | LB);
}
void L3G4200D_read_data(){
uint32_t result=0;
I2CWriteLength[PORT_USED] = 2;
I2CReadLength[PORT_USED] = 6;
I2CMasterBuffer[PORT_USED][0] = L3G4200D_WRITE_ADDR;
I2CMasterBuffer[PORT_USED][1] = (L3G4200D_DATA_ADDR | (1<<7));
I2CMasterBuffer[PORT_USED][2] = L3G4200D_READ_ADDR;
result=I2CEngine( PORT_USED );
gyro_X = make_word(I2CSlaveBuffer[PORT_USED][1], I2CSlaveBuffer[PORT_USED][0]);
gyro_Y = make_word(I2CSlaveBuffer[PORT_USED][3], I2CSlaveBuffer[PORT_USED][2]);
gyro_Z = make_word(I2CSlaveBuffer[PORT_USED][5], I2CSlaveBuffer[PORT_USED][4]);
}
/*
===============================================================================
Name : main.c
Author : $(author)
Version :
Copyright : $(copyright)
Description : main definition
===============================================================================
*/
#ifdef __USE_CMSIS
#include "LPC17xx.h"
#endif
signed short gyro_X, gyro_Y, gyro_Z;
volatile uint32_t msTicks;
__INLINE static void delay_ms (uint32_t delayTicks) {
uint32_t currentTicks;
currentTicks = msTicks; // read current tick counter
while ((msTicks - currentTicks) < delayTicks);
}
#include <cr_section_macros.h>
#include <NXP/crp.h>
#include "uart2.h"
#include <stdio.h>
#include "i2c.h"
#include "L3G4200D.h"
float x1,y1,z1;
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);
}
I2C1Init(); // Inicializamos el bus I2C
L3G4200D_init(); // Inicializamos el Gyróscopo
UART2_Init(57600); // Inicializamos el UART a 57600
UART2_PrintString ("\r\nGiroscopo L3G4200D\r\n");
UART2_PrintString ("======== elgarbe ==========\r\n");
UART2_PrintString ("\r\nRAW X\tRAW Y\tRAW Z\r\n");
while ( 1 ){
L3G4200D_read_data();
uart2_printInt32(gyro_X, 10);
UART2_Sendchar('\t');
uart2_printInt32(gyro_Y, 10);
UART2_Sendchar('\t');
uart2_printInt32(gyro_Z, 10);
UART2_Sendchar('\r');
UART2_Sendchar('\n');
delay_ms(500);
}
}
void L3G4200D_GetBiass(void){
int i;
for (i = 0; i < SAMPLESS_BIASS; i += 1) {
L3G4200D_read_data();
biass_X += gyro_X;
biass_Y += gyro_Y;
biass_Z += gyro_Z;
delay_ms(1);
}
biass_X /= SAMPLESS_BIASS;
biass_Y /= SAMPLESS_BIASS;
biass_Z /= SAMPLESS_BIASS;
}
/*
===============================================================================
Name : main.c
Author : $(author)
Version :
Copyright : $(copyright)
Description : main definition
===============================================================================
*/
#ifdef __USE_CMSIS
#include "LPC17xx.h"
#endif
#define GYRO_X_SCALE 0.07 //Sensibilidad en cada eje
#define GYRO_Y_SCALE 0.07 //extraído del datasheet
#define GYRO_Z_SCALE 0.07
#define SAMPLESS_BIASS 600 //Número de muestras para calular biass
signed short gyro_X, gyro_Y, gyro_Z;
double biass_X, biass_Y, biass_Z;
volatile uint32_t msTicks;
__INLINE static void delay_ms (uint32_t delayTicks) {
uint32_t currentTicks;
currentTicks = msTicks; // read current tick counter
while ((msTicks - currentTicks) < delayTicks);
}
#include <cr_section_macros.h>
#include <NXP/crp.h>
#include <math.h>
#include "uart2.h"
#include <stdio.h>
#include "i2c.h"
#include "L3G4200D.h"
void SysTick_Handler(void) {
msTicks++; /* increment counter necessary in Delay() */
}
/*******************************************************************************
** Main Function main()
*******************************************************************************/
int main (void){
double gx, gy, gz;
//Configuro el SysTick para que interrumpa cada 1mseg
if (SysTick_Config(SystemCoreClock / 1000)) {
while (1);
}
I2C1Init(); // Inicializamos el bus I2C
L3G4200D_init(); // Inicializamos el Gyróscopo
UART2_Init(57600); // Inicializamos el UART a 57600
UART2_PrintString ("\r\nGiroscopo L3G4200D\r\n");
UART2_PrintString ("======== elgarbe =========\r\n");
UART2_PrintString ("Obteniendo Offset...\r\n");
L3G4200D_GetBiass();
UART2_PrintString ("Offset X: ");
uart2_printDouble(biass_X, 4);
UART2_PrintString("\r\n");
UART2_PrintString ("Offset Y: ");
uart2_printDouble(biass_Y, 4);
UART2_PrintString("\r\n");
UART2_PrintString ("Offset Z: ");
uart2_printDouble(biass_Z, 4);
UART2_PrintString("\r\n");
UART2_PrintString ("\r\nRAW X\tRAW Y\tRAW Z\tdps X\tdps Y\tdps Z\r\n");
while ( 1 ){
L3G4200D_read_data();
gx=((float)gyro_X - biass_X);
gy=((float)gyro_Y - biass_Y);
gz=((float)gyro_Z - biass_Z);
uart2_printDouble(gx , 2);
UART2_Sendchar('\t');
uart2_printDouble(gy , 2);
UART2_Sendchar('\t');
uart2_printDouble(gz , 2);
UART2_Sendchar('\t');
gx *= GYRO_X_SCALE;
gy *= GYRO_Y_SCALE;
gz *= GYRO_Z_SCALE;
uart2_printDouble(gx, 3);
UART2_Sendchar('\t');
uart2_printDouble(gy, 3);
UART2_Sendchar('\t');
uart2_printDouble(gz, 3);
UART2_PrintString("\r\n");
delay_ms(500);
}
}
#ifdef __USE_CMSIS
#include "LPC17xx.h"
#endif
#define GYRO_X_SCALE 0.07 //Sensibilidad en cada eje
#define GYRO_Y_SCALE 0.07 //extraído del datasheet
#define GYRO_Z_SCALE 0.07
#define SAMPLESS_BIASS 600 //Número de muestras para calular biass
signed short gyro_X, gyro_Y, gyro_Z;
double biass_X, biass_Y, biass_Z;
volatile uint32_t msTicks;
__INLINE static void delay_ms (uint32_t delayTicks) {
uint32_t currentTicks;
currentTicks = msTicks; // read current tick counter
while ((msTicks - currentTicks) < delayTicks);
}
#include <cr_section_macros.h>
#include <NXP/crp.h>
#include <math.h>
#include "uart2.h"
#include <stdio.h>
#include "i2c.h"
#include "L3G4200D.h"
int timeStep = 20; //Tiempo que tiene que durar el main
void SysTick_Handler(void) {
msTicks++; /* increment counter necessary in Delay() */
}
/*******************************************************************************
** Main Function main()
*******************************************************************************/
int main (void){
double gx=0.0, gy=0.0, gz=0.0;
uint32_t timer=0;
//Configuro el SysTick para que interrumpa cada 1useg
if (SysTick_Config(SystemCoreClock / 1000)) {
while (1);
}
I2C1Init(); // Inicializamos el bus I2C
L3G4200D_init(); // Inicializamos el Gyróscopo
UART2_Init(57600); // Inicializamos el UART a 57600
UART2_PrintString ("\r\nGiroscopo L3G4200D\r\n");
UART2_PrintString ("======== elgarbe =========\r\n");
UART2_PrintString ("Obteniendo Offset...\r\n");
L3G4200D_GetBiass();
UART2_PrintString ("Offset X: ");
uart2_printDouble(biass_X, 4);
UART2_PrintString("\r\n");
UART2_PrintString ("Offset Y: ");
uart2_printDouble(biass_Y, 4);
UART2_PrintString("\r\n");
UART2_PrintString ("Offset Z: ");
uart2_printDouble(biass_Z, 4);
UART2_PrintString("\r\n");
UART2_PrintString ("\r\n° X\t° Y\t° Z\r\n");
timer = msTicks; //get a start value to determine the time the loop takes
while ( 1 ){
L3G4200D_read_data();
gx += (((float)gyro_X - biass_X) * GYRO_X_SCALE) * timeStep/1000;
gy += (((float)gyro_Y - biass_Y) * GYRO_Y_SCALE) * timeStep/1000;
gz += (((float)gyro_Z - biass_Z) * GYRO_Z_SCALE) * timeStep/1000;
uart2_printDouble(gx, 3);
UART2_Sendchar(',');
uart2_printDouble(gy, 3);
UART2_Sendchar(',');
uart2_printDouble(gz, 3);
// UART2_Sendchar(',');
// uart2_printInt32(msTicks, 10);
UART2_PrintString("\r\n");
timer=msTicks-timer; // Obtengo cuánto tiempo pasó en el bucle
timer=timeStep-timer; // Obtengo lo que falta para llegar al timeStep
delay_ms(timer); // Espero hasta llegar al timeStep
timer=msTicks;
}
}
Tengo entendido que el "Rate Noise Density"(Rn) como bien dices es el ruido del sensor.
Generalmente se denota el efecto del ruido por este parámetro o por el "Angular Random Walk".
La formula del Ruido del sensor está dada por: Ruido Sensor=(Rate Noise Density)*sqrt(Ancho de banda)
A más ancho de banda, más ruido se verá en el sensor.
Tal Rn se puede representar como la fluctuación de la medida del sensor. Para el caso de este sensor el ruido del sensor será 0.03*sqrt(50)=0.212 dps, con la condición de que el ancho de banda sea de 50Hz como dice en el diagrama.
hay otros parámetros que también afectan al ruido total, pero para hallar el "ruido total"(RT) es:
RT=sqrt(Rn + .....), con este ejemplo y considerando solo el Rn, el RT dá aprox 0.46 dps.
Como dije otro parámetro común de encontrar en los gyros u otros sensores es en "Angular Random Walk"
Para convertir el "Rate Noise Density" a "Angular Random Walk"(ARW) solo se multiplica por 60.
Por ejemplo en este caso el Rn=0.03dps/sqrt(Hz)
entonces el ARW=0.03*60=1.8 grados/sqrt(hora), el ARW describe la desviación promedio cuando se integra la señal. Independientemente de otras características que contribuyen al error angular(como el factor escala o las bias).
El error incrementará a lo largo de la integración, por ejemplo para este caso dentro de una hora la desviación angular promedio será de 1.8*sqrt(1)=1.8 grados, después de 2 horas será 1.8*sqrt(2)= 2.54 grados.
Ya que tu micro puede correr más rápido puedes mostrar los resultados a su máximo muestreo y ver como se comporta. yo no pude llegar ya que con toda la transmisión serial llegaba a 8ms.
a mediados de la prox. semana retomo el navegador inercial en el trabajo, ya que aún tengo problemas. Ahora estoy acabando otro proyecto, que me consume todo el tiempo.
Gracias por seguir compartiendo. Así animas a profundizase más en el tema.
saludos.
Giroscopo L3G4200D
======== elgarbe =========
Obteniendo Offset,,,
Off X Off Y Off Z
14,7650 -6,6450 -16,9767
13,6813 -6,2011 -16,2850
16,4128 -6,9820 -16,1655
14,1807 -6,1783 -15,8136
12,0853 -6,1503 -15,4730
11,4201 -6,4936 -15,4841
14,6824 -7,7158 -17,5491
14,1978 -6,6879 -16,6009
11,2137 -6,3128 -15,8093
13,4737 -6,7789 -15,9997
14,6541 -7,7446 -17,3417
15,6844 -5,6879 -16,4706
15,7995 -6,9811 -17,2991
12,5280 -6,6216 -16,2238
15,0509 -7,4894 -17,0370
12,1918 -7,4025 -15,7367
10,7087 -5,5807 -15,0629
14,6795 -6,5976 -17,2384
17,5895 -6,3977 -17,2421
14,3876 -6,6740 -17,2337
17,1590 -6,1561 -17,3587
12,9019 -8,3619 -17,2173
16,6715 -5,5073 -16,5554
11,5845 -4,4708 -14,5943
14,3793 -5,1458 -14,9893
14,3073 -5,5852 -15,9983
15,4022 -5,8226 -15,3983
15,7257 -5,6230 -16,9540
17,4695 -6,1977 -17,3816
12,4408 -6,7937 -17,0023
15,8257 -5,3447 -16,0317
15,0364 -7,8256 -18,6051
15,1984 -5,7264 -16,8127
15,7703 -7,0829 -17,5664
12,4696 -6,8835 -16,2193
14,5774 -6,3431 -16,2870
13,7460 -6,8506 -17,4171
16,0412 -7,1298 -17,6457
13,0134 -7,0202 -17,0961
15,7667 -6,5450 -17,1052
15,2813 -6,0992 -17,0935
14,8471 -7,7768 -18,2035
12,7764 -6,0563 -16,0737
15,6930 -5,7568 -16,3551
15,7678 -6,5696 -16,6073
14,8113 -7,0726 -17,9110
13,0630 -8,0501 -17,9765
14,6934 -4,5884 -15,0300
12,2912 -6,6126 -16,9900
14,7655 -6,7760 -17,1867
14,3773 -6,5019 -16,6541
Cuanto más muestras obtienes para obtener el offset menor es la variación en cada cálculo del offset, ya que se obtiene más datos del ruido involucrado. Yo hago algo parecido como tu pero en vez de calcular 50 veces el offset con 600 muestras, calculo el offset solo una vez con 3000 muestras.
Como analizaste en las graficas el calculo en el offset nunca va a ser constante, parece que es por la variación de la temperatura ya que es un factor importante en la suma del ruido.
Viendo en el datasheet del sensor que uso mpu6050, un dato nos da esta variación: "Sensitivity change vs Temperature" = +-0.02%/grados centigrados
lo cual nos dice que por cada variación de 1 grados centigrado tenemos una variación de +-2% de lo sensado.
En el sensor que uso en promedio en cada lectura la temperatura varia 0.19 miligrados. el cual parte de casi 26 grados hasta 32 grados después de varios segundos en el cual se estabiliza, pero siempre variando.
Puede ser que el mayor ruido que viste en el ejex, sea aleatorio, en mi caso cada vez que hago pruebas. a veces el ejex, ejey o ejez son más ruidosos.
Y las pruebas que estas haciendo es para movimientos lentos, podrías hacer pruebas para movimientos bruscos, ya que en el comportamiento real será asi. En las pruebas que hice cuando hago movimientos bruscos, el sensor se desvia demasiado en pocos segundos. por ejemplo de 0,0,0 a 66,4,88. o a otros valores pero el desvió es demasiado.
GYRO SCALED x:0.06,y:-0.10,z:0.02
GYRO RAW x:-010,y:0003,z:0005
GYRO SCALED x:0.00,y:-0.03,z:-0.04
GYRO RAW x:-010,y:0003,z:0005
GYRO SCALED x:0.06,y:-0.03,z:0.02
GYRO RAW x:-010,y:0003,z:0006
GYRO SCALED x:0.06,y:-0.03,z:-0.04
GYRO RAW x:-011,y:0002,z:0004
GYRO SCALED x:0.13,y:-0.10,z:-0.18
GYRO RAW x:-010,y:0003,z:0004
GYRO SCALED x:0.06,y:-0.10,z:-0.04
GYRO SCALED x:0.20,y:0.10,z:-2.35
GYRO RAW x:-039,y:-437,z:-571
GYRO SCALED x:-11.97,y:-6.26,z:-363.62
GYRO RAW x:0005,y:0427,z:-921
GYRO SCALED x:-5.32,y:-9.20,z:-272.97
GYRO RAW x:-007,y:-008,z:0329
GYRO SCALED x:0.00,y:0.10,z:18.01
GYRO RAW x:-010,y:0005,z:0192
GYRO SCALED x:0.06,y:0.03,z:15.21
Pero que buena codificacion!!!! Ojalá yo fuses tan prolijo con el código!!!!
En principio, si solo lees los datos raw y luego le sacas el offset y lo escalas lo que obtienes es la velocidad angular. Entonces, por más que des un giro completo los datos que mostrás pueden estar bien o no... depende de con que velocidad lo estés girando....
Para obtener el ángulo de giro debes hacer la integracion discreta, es mas o menos como vos dijiste, al angulo actual le sumas la velocidad leída x el tiempo de muestreo.
* timeStep/1000; ----> por que es el tiempo de muestreo dividido 1000 ? Si uso el RTOS...el timeStep serian los 50ms que le indico para que realice la adquisición ?
Con respecto a la aplicación, es para un sistema de navegación en un robot móvil. En estos momentos estoy tratando de entender la física y demás parámetros para poder
implementarlo con un PIC trabajando a 12mips a 48Mhz....o 16Mips a 64Mhz.
Ya tengo librerías desarrolladas para HCM5883L (magnetómetro), BMP085 (barómetro - falta función para determinar la altura con respecto a nivel del mar), ADXL345 (acelerómetro - falta función para escalar los datos y obtener la aceleración en Gs)..y algunas otras funciones más y dispositivos como el GPS que se irán integrando con el tiempo.
En mi caso timeStep vale 20 (mseg). Lo divido por 1000 para que quede en segundos, ya que el sensor nos etrega rad/seg debemos multiplicar por el tiempo en segundos. Me explico?
Tengo el barometro funcionando, pero aún no hice tiempo de postearlo. Fijate en este subforo que he escrito sobre el acelerómetro también.
No me imagino la navegacion de un robot con acelerómetros, gyros y demás. Me gustaría saber más de tu desarrollo...
Has hecho pruebas de como te da el azimut para ángulos de cabeceo o banqueo superiores a +-40 grados?, se que se puede solucionar con el giroscopo, pero con el magnetómetro solo?
Quiero darle a un robot, una posición X,Y dentro de una zona a campo abierto y que se guíe por IMU+GPS. Luego quiero darle la misma dirección X,Y dentro de una zona cerrada y que se guíe por radar + cámara + odometría. Es un proyecto ambicioso, pero por ahora estoy aprendiendo...no se nada sobre navegación ni tampoco mucho sobre sistemas
de control de lazo cerrado complejos...
CitarHas hecho pruebas de como te da el azimut para ángulos de cabeceo o banqueo superiores a +-40 grados?, se que se puede solucionar con el giroscopo, pero con el magnetómetro solo?
Disculpá mi ignorancia, pero no entiendo tu pregunta :(
Tengo entendido que podes obtener con cierta presicion la orientacion (léase, rotación) del objeto. Para obtener la posicion deberías integrar 2 veces la medicion del acelerómetro por ejemplo (verdad?) y tengo entendido que la primera integra aporta deriva y una segunda integral hace ilegible la medicion.
El proyecto es muy, pero muy interesante! todo lo que quieras y puedas compartir será bienvenido ya que será de utilidad para el resto de los proyectos que pueden aparecer en este foro y sin duda me será de utilidad para mi controladora de vuelo.
Lo que pregunta es si has probado la medicion del ángulo (respecto del norte) pero inclinando tu magnetómetro.