PIC: HMC5883 - Magnetômetro de 3 Eixos
HMC5883 é um magnetômetro digital de 3 eixos projetado para detecção de campos magnéticos. O sensor tem um alcance em larga escala de ± 8 Gauss e uma resolução de até 5 miliGauss.
A comunicação com o HMC5883L é simples e tudo feito através de uma interface I2C.
No próximo post, iremos criar uma bússola digital, isso mostrará em que direção esta apontando em graus. Ao ler 0° estará apontando para o polo norte magnético, e 180° quando estamos apontando para o polo sul magnético.
Como a bússola detecta campos magnéticos, qualquer material ferroso por perto pode afetar consideravelmente sua saída ( Estou vendo mais um projeto aí! Que tal fazermos um detector de metais? ).
REGISTROS
Configuration Register A: É usado para configurar o dispositivo para a fixação da taxa de saída de dados e configuração de medição.
Configuration Register B: Ajusta o ganho do dispositivo.
Mode Register: Este registo é utilizado para selecionar o modo de funcionamento do dispositivo. (Medição Continua ou Medição Simples).
Data Output Register: Esses registros armazenam o resultado da medição da saída de dados.
Identification Register: É usado para identificar o dispositivo.
BIBLIOTECA
#include <built_in.h>
//Para utilizar o software_i2c...ou o i2c interno
#ifdef USE_HMC5883_SOFT_I2C
#define HMC5883_I2C_Wr Soft_I2C_Write
#define HMC5883_I2C_Rd Soft_I2C_Read
#define HMC5883_I2C_Stop Soft_I2C_Stop
#define HMC5883_I2C_Start Soft_I2C_Start
#define HMC5883_I2C_Repeated_Start Soft_I2C_Start
#else
#define HMC5883_I2C_Wr I2C1_Wr
#define HMC5883_I2C_Rd I2C1_Rd
#define HMC5883_I2C_Stop I2C1_Stop
#define HMC5883_I2C_Start I2C1_Start
#define HMC5883_I2C_Repeated_Start I2C1_Repeated_Start
#endif
#define CONFIGURATION_REG_A 0x00
#define CONFIGURATION_REG_B 0x01
#define MODE_REG 0x02
#define DATA_OUTPUT_REG 0x03
#define STATUS_REG 0x09
#define IDENTIFICATION_REG_A 0x0A
#define IDENTIFICATION_REG_B 0x0B
#define IDENTIFICATION_REG_C 0x0C
//Scale
#define _088Ga 0
#define _13Ga 32
#define _19Ga 64
#define _25Ga 96
#define _40Ga 128
#define _47Ga 160
#define _56Ga 192
#define _81Ga 224
#define HMC5883_ADDRESS 0x3C
typedef struct
{
float X;
float Z;
float Y;
unsigned Angle;
unsigned MagneticField;
}HCM5883_Magnetometer;
static float hmc5883_scale;
void HMC5883_Init()
{
hmc5883_scale = 0.92;
HMC5883_I2C_Start();
HMC5883_I2C_Wr( HMC5883_ADDRESS );
HMC5883_I2C_Wr( CONFIGURATION_REG_B );
HMC5883_I2C_Wr( 32 );
HMC5883_I2C_Wr( 0x00 ); //Continuo
HMC5883_I2C_Stop();
}
void HMC5883_Read( HCM5883_Magnetometer *Mag )
{
signed int tmp;
float heading;
unsigned magF[3];
HMC5883_I2C_Start();
HMC5883_I2C_Wr( HMC5883_ADDRESS );
HMC5883_I2C_Wr( DATA_OUTPUT_REG );
HMC5883_I2C_Repeated_Start();
HMC5883_I2C_Wr( HMC5883_ADDRESS | 1 );
Hi(tmp) = HMC5883_I2C_Rd(1);
Lo(tmp) = HMC5883_I2C_Rd(1);
Mag->X = (tmp * hmc5883_scale);
Hi(tmp) = HMC5883_I2C_Rd(1);
Lo(tmp) = HMC5883_I2C_Rd(1);
Mag->Z = (tmp * hmc5883_scale);
Hi(tmp) = HMC5883_I2C_Rd(1);
Lo(tmp) = HMC5883_I2C_Rd(0);
Mag->Y = (tmp * hmc5883_scale);
HMC5883_I2C_Stop();
heading = atan2( Mag->Y, Mag->X );
//heading += declinationAngle; //http://www.magnetic-declination.com/
if( heading < 0 )
{
heading += 6.283185307;
}
Mag->Angle = ((heading * 180) / 3.141592654);
magF[0] = Mag->X / 10;
magF[1] = Mag->Y / 10;
magF[2] = Mag->Z / 10;
Mag->MagneticField = sqrt( (magF[0]*magF[0]) + (magF[1]*magF[1]) + (magF[2]*magF[2]) ); //uT
}
void HMC5883_SetScale( char scale )
{
switch( scale )
{
case 0: hmc5883_scale = 0.73; break;
case 32: hmc5883_scale = 0.92; break;
case 64: hmc5883_scale = 1.22; break;
case 96: hmc5883_scale = 1.52; break;
case 128: hmc5883_scale = 2.27; break;
case 160: hmc5883_scale = 2.56; break;
case 192: hmc5883_scale = 3.03; break;
case 224: hmc5883_scale = 4.35; break;
default: hmc5883_scale = 0.92; break;
}
HMC5883_I2C_Start();
HMC5883_I2C_Wr( HMC5883_ADDRESS );
HMC5883_I2C_Wr( CONFIGURATION_REG_B );
HMC5883_I2C_Wr( scale );
HMC5883_I2C_Stop();
}
EXEMPLO:
/*
Projeto: Leitura do Sensor HMC5883 e Display Nokia3310
Autor: Tiago Henrique
*/
//Habilitar as seguintes bibliotecas:
// - I2C
// - Conversions e C_String
//Bibliotecas salvas em um arquivo externo
#include "hmc5883.h"
#include "nokia3310.h" //procure no blog a biblioteca!!!
sbit Nokia_SCE at RB3_Bit;
sbit Nokia_RST at RB4_Bit;
sbit Nokia_DC at RB5_Bit;
sbit Nokia_MOSI at RB6_Bit;
sbit Nokia_CLK at RB7_Bit;
sbit Nokia_SCE_Direction at TRISB3_Bit;
sbit Nokia_RST_Direction at TRISB4_Bit;
sbit Nokia_DC_Direction at TRISB5_Bit;
sbit Nokia_MOSI_Direction at TRISB6_Bit;
sbit Nokia_CLK_Direction at TRISB7_Bit;
HCM5883_Magnetometer Mag;
char msg[12];
void main()
{
Nokia_Init(); //inicia o display
Nokia_Clear(); //limpa a tela do display
ADCON1 = 0x0F; //desativa o canal analogico
I2C1_Init(); //Inicializa o módulo I2C
HMC5883_Init(); //inicializa o sensor
CMCON = 7; //desativa os comparadores analogicos
while(1)
{
//Faz a leitura do sensor
HMC5883_Read( &Mag );
//Converte o valor do "eixo X" para string
IntToStr( Mag.X, msg );
Nokia_Set_Cursor(0,0); //Seta a posicao do cursor
Nokia_Out( "X: ", BLACK );
LTrim(msg); //Limpa os espaços a esquerda
Nokia_Out( msg, BLACK ); //Imprime na tela
IntToStr( Mag.Y, msg );
Nokia_Set_Cursor(0,1);
Nokia_Out( "Y: ", BLACK );
LTrim(msg);
Nokia_Out( msg, BLACK );
IntToStr( Mag.Z, msg );
Nokia_Set_Cursor(0,2);
Nokia_Out( "Z: ", BLACK );
LTrim(msg);
Nokia_Out( msg, BLACK );
WordToStr( Mag.Angle, msg );
Nokia_Set_Cursor(0,3);
Nokia_Out( "A: ", BLACK );
LTrim(msg);
Nokia_Out( msg, BLACK );
WordToStr( Mag.MagneticField, msg );
Nokia_Set_Cursor(0,4);
Nokia_Out( "M: ", BLACK );
LTrim(msg);
Nokia_Out( msg, BLACK );
Nokia_Out( "uT", BLACK );
Delay_ms(500);
}
}


Primeiramente queria elogiar pelo competência e qualidade do blog :)... caro amigo, eu baixei o modelo simulavel do arduino uno para o proteus... muito bom mesmo!!! esse HMC5883L tem no proteus tbm? eh simulavel? como faço para baixar?
ResponderExcluirMuito obrigado!!
ExcluirSeria bom se pudesse simular, mas é só um modelo.
Abraços.
Excelente página com projetos incríveis. Estou tendo um problema na leitura dos dados que só consegue ser contínuo quando o endereço 03 (X MSB) tem o valor 255. Qual a grande besteira que estou fazendo? A ideia é montar um anemômetro com indicação de sentido do vento.
ResponderExcluirEduardo
Estou tentando fazer a mesma coisa você teve sucesso?
Excluiro anemômetro está funcionando para dar a indicação do vento estou com alguns problemas
se pode me ajudar entre em contato. Obrigado
pascoal.forgiarini@hotmail.com
Hi Sir,
ResponderExcluirI need HMC5882L library for proteus
please send to my email.
my email anilbatade98@gmail.com
thank you.
amigo, está dando erro ao compilar a nnokia3310.h
ResponderExcluirchr = BigNumbers[n][i]; dá como não declarado BigNumbers