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