Problema con Magnetómetro HMC5883L

Hola, que tal. Esta es mi primera pregunta en el foro, es que espero que obtenga buenos resultados. Estoy trabajando con un sensor, específicamente el HMC5883L que es un magnetómetro de la compañía Honeywells. Estoy tratando de adquirir los valores de campo magnético en uno de los tres ejes coordenados. El sensor se compone de 6 registros internos expresados del registro 0X03 al 0X08. El sensor mide el campo magnético que afecte a cada uno de los ejes y dependiendo de la intensidad de éste cambiarán los valores que son almacenados en registros. Cada valor de campo magnético tiene una representación en 16 bits en complemento a dos, esto quiere decir que los valores que son muestreados permiten signos negativos, al encontrarse con estos se aplica el complemento a dos. El sensor presenta 16 bits por cada posición X,Y y Z pero los distribuye en registros internos de 8 bits, esto quiere decir que existen 2 registros independientes para guardar el valor de la posición en cada eje. El eje X, Y y Z se componen de 2 registros de 1Byte (XMSB y XLSB, igualmente para Y y Z). Las hojas de especificación indican que pueden ser leídos valores desde -2048 a 2047 en decimal, o lo que es igual de 0XF800 al 0X07FF. Mi problema es que he estado muestreando los valores en cada uno de los ejes y tengo problemas con el Byte más significativo (XMSB) ya que solo me muestra los valores 0XFF, 0XFE, 0XFD(en ocasiones), 0X00 y 0X01. El byte menos significativo parece no tener problemas. ya que he observado que cambia continuamente de valores desde 0X00 a 0XFF. El problema está en el Byte más significativo. Los datos que arroja el sensor son comunicados a través de una interfaz I2C al PIC16F887. He estado buscando la solución a este problema pero no he podido dar con ella. He sido cuidadoso en revisar el circuito. He colocado las resistencias de Pull Up de 2.2k como lo indica la hoja de especificaciones. Estoy alimentando el circuito con dos fuentes independientes, por un lado alimento al PIC con 5v y al sensor con 3v ya que estoy utilizando una LCD para observar los datos que me arroja, la tierra de ambas fuentes está conectada a un punto común y las resistencias de Pull Up están conectadas a 5V. Para programar el PIC estoy utilizando el MikroC PRO, estoy utilizando las librerías de la I2C. Les dejo un ejemplo del código que estoy utilizando. No se si estoy adquiriendo mal los datos, pero la parte "extraña" es que solo los Bytes más significativos de cada eje tiene este problema, los Bytes menos significativos parecen estar bien. Espero me ayuden, me URGE una respuesta, Se los voy a agradecer mucho, he escuchado muy buenas opiniones sobre este foro.
 

Adjuntos

  • prueba1.pdf
    18 KB · Visitas: 45
Hola, en el ejemplo que pones no esta muy claro lo que hace,
esta constantemente leyendo los 6 registros de datos, es asi?
 
Si, lee continuamente los 6 registros, el problema es que los datos de los registros 0X03,0X05 Y 0X07 solo generan los valores 0XFF o 0XFE o 0X00. Según la hoja de datos del sensor HMC5883L los valores que el sensor puede generar está en un rango de entre -2048 a 2047 en decimal, por lo tanto los Bytes altos de las posiciones X, Y y Z no se están generando correctamente.
 
Por lo que pude entender antes de hacer las mediciones hay que
realizar cierta configuracion del dispositivo como ser indicarle si
va a ser medicion continua o simple, ademas creo que no se puede
leer continuamente sino hay que esperar a que se complete la medicion
para luego leer los regitros, eso lo sabes por medio de la interrupcion
DRDY o leyendo el bit RDY del STATUS REGISTER, ademas hay que definir
la Typical Data Output Rate que como maximo es de 160hz, as realizado alguna de estas
configuraciones.
Espero que este comentario te ayude en algo.
 
Hola, gracias por responder, si he realizado la configuración antes de empezar a leer los datos, en el código que pongo de ejemplo la configuración esta separa en tres secciones, la primera enviando la secuencia 0X3C,0X00,0X70 Que indica que la medición se hará en forma normal y que se van a adquirir paquetes de ocho datos. Después envío la secuencia 0X3C,0X01,0XA0 que configura la ganancia del sensor. Por último envío 0X3C,0X02,0X00 Que indica que se va a operar en modo continuo. Se siguen generando los mismos errores en los Bytes más significativos, el problema es que solo cambia de valor de 0x00 a 0xFF sin pasar por valores intermedio, y los Bytes menos significativos si lo hacen bien, o al menos eso parece. Espero me puedan ayudar, me URGE echar andar este sensor.
 
Me ha llegado de la China un modulo con HMC5883L
En la protoboard separé la alimentación del pic (16f876a 5V) y del módulo (aunque se dice que acepta tensiones de 5V lo estoy alimentando con un 78l03)
Las líneas del bus I2C(SDA y SCL) de distinto voltaje (3V del modulo y 5V del pic) son interconectados con con dos BS170 como switch-level.
Los valores rilevados son estos (en modalidad lectura constante y en modo single).
X=Nord
420
Y=Ovest
65506

X=Ovest
160
Y=Sud
65111

X=Sud
65349
Y=Est
65386

X=Est
48
Y=Nord
222
he leido y recontraleido el datasheet para escribir un programa en GCBasic(mod. lectura continua):
Código:
CHIP 16F877A,4
#CONFIG OSC=XT,WDT_OFF,PWRTE_ON,CP_OFF,DEBUG_OFF,WRT_OFF,CPD_OFF,LVP_OFF,BODEN_ON

#INCLUDE <I2C_Master.h>

DIM Contador,EjeXH,EjeXL,EjeZH,EjeZL,EjeYH,EjeYL AS INTEGER
DIM CurrentAddress AS WORD

SUB HMC5883L_Init()
START()
Tx_I2C(0x3C)
Tx_I2C(0x00)
Tx_I2C(0x70)
STOP()
START()
Tx_I2C(0x3C)
Tx_I2C(0x01)
Tx_I2C(0x20) 
STOP()
START()
Tx_I2C(0x3C)
Tx_I2C(0x02)
Tx_I2C(0x00)
STOP()
END SUB

FUNCTION HMC5883L_Test() AS INTEGER
DIM Test AS INTEGER
START()
Tx_I2C(0x3C)
Tx_I2C(0x02)
RESTART()
Tx_I2C(0x3D)
Test=Rx_I2C()
STOP()
HMC5883L_Test=Test
END FUNCTION

SUB HMC5883L_Lectura()
START()
Tx_I2C(0x3C)
Tx_I2C(0x03)
RESTART()
Tx_I2C(0x3D)
EjeXH=Rx_I2C()
ACK_I2C()
EjeXL=Rx_I2C()
ACK_I2C()
EjeZH=Rx_I2C()
ACK_I2C()
EjeZL=Rx_I2C()
ACK_I2C()
EjeYH=Rx_I2C()
ACK_I2C()
EjeYL=Rx_I2C()
No_ACK_I2C()
STOP()
END SUB

Ciclo:
      TRISA=b'000000'
      TRISB=b'00000000'
      TRISC=b'00011000'
      TRISD=b'00000000'
      TRISE=b'00000000'
      PORTA=b'000000'
      PORTB=b'00000000'
      PORTC=b'00000000'
      PORTD=b'00000000'
      PORTE=b'00000000'
      INTCON=b'00000000'
      OPTION_REG=b'00000000'
      CVRCON=b'00000000'
      CCP1CON=b'00000000'
      CCP2CON=b'00000000'
      ADCON0=b'00000000'
      ADCON1=b'10000110'
      I2C_Init(4000,100)
      CurrentAddress=0
      IF HMC5883L_Test=3 THEN
         SET PORTD.2 OFF
         SET PORTD.3 ON
      ELSE
         SET PORTD.2 ON
         SET PORTD.3 OFF
         GOTO Ciclo
      END IF
      HMC5883L_Init()
      WAIT 100 ms
      SET PORTD.0 ON
      FOR Contador=0 TO 41
          HMC5883L_Lectura()
          EPWrite CurrentAddress,"X"
          CurrentAddress+=1
          EPWrite CurrentAddress,EjeXH
          CurrentAddress+=1
          EPWrite CurrentAddress,EjeXL
          CurrentAddress+=1
          EPWrite CurrentAddress,"Y"
          CurrentAddress+=1
          EPWrite CurrentAddress,EjeYH
          CurrentAddress+=1
          EPWrite CurrentAddress,EjeYL
          CurrentAddress+=1
          WAIT 200 ms
      NEXT
      SET PORTD.0 OFF
      SET PORTD.2 OFF
      SET PORTD.3 OFF
La función HMC5883L_Test() hace un test del bus I2C.
Si la respuesta del módulo es justa, se enciende el led verde y el programa sigue adelante con la lectura.
Si no responde correctamente se enciende el led rojo y va en loop (GOTO Ciclo)
Como se ve la lectura del eje x +- corresponden según datasheet.
Si alguno ya trabajo con estas cosas chinas por favor me diga donde me equivoco.

Pido disculpa a todo el foro. ¿Cómo puedo escribir un valor negativo en una eeprom? :oops:
 
x JavierUpita
haz encontrado una solucòn??:confused:.yo sigo leyendo los mismo valores con todas las configuraziones.por ejemplo:
<== X: 1 148 404
<== Y:255 216 65496
<== Z:253 164 64932

<== X: 0 149 149
<== Y:254 106 65130
<== Z:253 165 64933

<== X:255 42 65322
<== Y:255 135 65415
<== Z:253 180 64948

<== X: 0 49 49
<== Y: 1 9 265
<== Z: 253 176 64944
X: MSB LSB (MSB<<8)|LSB
por favor alguno encontro la solucion
 
¿En que ambiente haces las mediciones?
Tal vez algún campo magnético de algún equipo te esté alterando las mediciones.
¿V
erificaste esto?
 
Última edición por un moderador:
Sobre la mesa de la cocina (es mi laboratorio cuando mi mujer me lo permite) y cerca del pc.
Mañana haré las pruebas en el jardín de casa.
 
Última edición por un moderador:
provado en el jardin de casa.el objeto metalico que esta màs cerca a 5 metros.
Configuraciòn:
0x3C 0x00 0x70 (8 campionamentos --- Freq. respuesta=15Hz --- Configuraciòn mediciòn normal)
0x3C 0x01 0xA0 (Lapso campo sensor=4.7Ga --- 390 Gain(LSb/Gauss))
0x3C 0x02 0x00 (Modo lectura continua)
Envio un pedido de control sul registro 0x02:
0x3C 0x02 RESTART 0x3D
Si responde con un 0x03 parte el programa de lectura continua(he provado tambien en singola con los mismos valores en las mismas posiziones)
Comienza a leer los datos que envia el modulo con estos resultados:
SUR
---------------
X:000-039 39
Y:255-108 65388
Z:255-045 65325

SUR/ESTE
---------------
X:255-216 65496
Y:255-139 65419
Z:255-046 65326

ESTE
---------------
X:255-173 65453
Y:255-230 65510
Z:255-048 65328

NORD/ESTE
---------------
X:255-213 65493
Y:000-069 69
Z:255-051 65331

NORD
---------------
X:000-019 19
Y:000-098 98
Z:255-049 65329

NORD/OESTE
---------------
X:000-110 110
Y:000-062 62
Z:255-045 65325
Este es el codigo en GCBasic de lectura:
Código:
SUB HMC5883L_Lectura()
START()
Tx_I2C(0x3C)
Tx_I2C(0x03)
RESTART()
Tx_I2C(0x3D)
X_Tmp(0)=Rx_I2C()
ACK_I2C()
X_Tmp(1)=Rx_I2C()
ACK_I2C()
Z_Tmp(0)=Rx_I2C()
ACK_I2C()
Z_Tmp(1)=Rx_I2C()
ACK_I2C()
Y_Tmp(0)=Rx_I2C()
ACK_I2C()
Y_Tmp(1)=Rx_I2C()
No_ACK_I2C()
STOP()
EjeX=(X_Tmp(0)*256)
EjeX+=X_Tmp(1)
EjeY=(Y_Tmp(0)*256)
EjeY+=Y_Tmp(1)
EjeZ=(Z_Tmp(0)*256)
EjeZ+=Z_Tmp(1)
END SUB
por favor,cosa esta pasando:cry:
el sensor no funziona bien?
 
Última edición:
ok,esta iniciando a trabajar :D :
SUR
---------------
X 55
Y 65394
Z 65328
Grados=317°

ESTE
---------------
X 65457
Y 65499
Z 65332
Grados=250°

NORD
---------------
X 31
Y 95
Z 65334
Grados=91°

OESTE
---------------
X 141
Y 0
Z 65330
Grados=19°
como se ve,el minimo angulo relevado es 19°(en vez de 0°) y el maximo es 317°(en vez de 360°).
con este codigo en Gambas2 puedo leer los datos en rotaciòn(partiendo desde Oeste)en sentido horario.
va desde 19° hasta 317° un grado a la vez:
Código:
PUBLIC SUB RS232_Read()
DIM strInput AS String
TRY READ #RS232, strInput, 1
IF ERROR THEN
   txaVentana.Text &= "--> Error de recepciòn" & "\n"
ELSE
   IF Asc(strInput) <> 13 THEN
      Frase &= strInput
   ELSE
      Analisar(Frase)
      Frase = ""
   ENDIF
ENDIF
END

PUBLIC SUB Analisar(Linea AS String)
DIM Angulo, Declinacion AS Float
DIM Puntador_X, Puntador_Y, Puntador_Z AS Integer
DIM NumeroX, NumeroY, NumeroZ AS Long
Declinacion = 0.3333
Puntador_X = InStr(Linea, "X")
Puntador_Y = InStr(Linea, "Y")
Puntador_Z = InStr(Linea, "Z")
NumeroX = CLong(Trim(Mid(Linea, Puntador_X + 1, (Puntador_Y - Puntador_X) - 1)))
NumeroY = CLong(Trim(Mid(Linea, Puntador_Y + 1, (Puntador_Z - Puntador_Y) - 1)))
NumeroZ = CLong(Trim(Mid(Linea, Puntador_Z + 1, Len(Linea) - Puntador_Z)))
txbX.Text = Signo(NumeroX)
txbY.Text = Signo(NumeroY)
txbZ.Text = Signo(NumeroZ)
Angulo = Ang(Signo(NumeroX), Signo(NumeroY))
Angulo = Angulo + Declinacion
IF Angulo < 0 THEN Angulo += (2 * Pi)
IF Angulo > (2 * Pi) THEN Angulo -= (2 * Pi)
Angulo *= 180 / Pi
txbGrados.Text = CInt(Angulo)
END

FUNCTION Signo(Word AS Long) AS Integer
DIM Valor AS Integer
IF Word <= 2047 THEN
    Valor = Word
ELSE
    Valor = - (Word - 65280)
ENDIF
RETURN Valor
END
es un poco rudimentario,pero funziona:cool:
la declinaciòn es de 0.3333(Napoles,Italia).me permite de corregir la deriva con el polo geografico +- bien.
el error del 0°-360° tentare de corregirlo usando valores en Float en vez de Long(que es un entero y tal ves perjudique el calculo de los radianes en Ang(X,Y))
 
Última edición:
:D:D
Funciona mejor de lo que me esperaba.
modificando la configuraciòn de setup del modulo trabaja magnificamente:
0x3C 0x00 0x70 (8 campionamentos,15Hz,lectura en modo normal)
0x3C 0x01 0x40 (+-1.9Ga)
do
0x3C 0x02 0x01 (lectura singular,no en modo continuado)
WAIT 5 ms (como minimo)
Ir a la funciòn de lectura y leer la respuesta del modulo
WAIT 25 ms (como minimo)
Codigo de gestiòn de los datos adquiridos
WAIT 67 ms (como minimo)
loop
va desde 0° a 359° sin perder golpe.
 
Atrás
Arriba