O módulo Bússola Eletrônica HMC5883L permite determinar a direção do Norte através da medição do campo magnético da Terra. Neste post vamos ver alguns detalhes do seu funcionamento e sua interface com o Arduino e construir uma bússola eletrônica usando o módulo e um anel de LEDs RGB.
Material Necessário
- Arduino Nano
- Módulo Bússola Eletrônica HMC5883L
- Anel de LEDs RGB com 12 LEDs
- Protoboard
- Jumpers Macho-Macho
Conhecendo o módulo Bússola Eletrônica HMC5883L
Apesar do nome, este módulo não usa o chip HMC5883L, pois ele já foi descontinuado. No seu lugar é usado o QMC5833L, que foi desenvolvido a partir do licenciamento do HMC5883L, mas tem algumas diferenças. O princípio de funcionamento é igual nos dois chips: três sensores magnéticos medem a intensidade em três eixos (X, Y e Z). Estas medidas são convertidas em três números de 16 bits com sinal, através de um conversor analógico digital, e armazenadas em registradores internos.
A comunicação do módulo com um microcontrolador é feita através do protocolo I2C. Lembrando, esta é uma ligação a dois fios “em varal” onde cada dispositivo tem um endereço de 7 bits. No caso do QMC5833L, este endereço é 0x0D. As leituras e escritas nos registradores começam com uma operação de escrita I2C na qual é passado o número do registrador que será lido/escrito. Para simplificar, após cada leitura ou escrita o número do registrador a acessar é automaticamente incrementado, facilitando a leitura ou escrita de registradores consecutivos.
A figura abaixo mostra os registradores disponíveis e seus números. Reparar que o resultado da medição ocupa 6 registradores – um par para cada direção, com o byte menos significativo primeiro – na ordem X, Y e Z.
A correspondência dos eixos X, Y e Z com a posição física da placa pode ser observada através da indicação impressa no módulo HMC5883L:
Um problema com os módulos de bússola é que as leituras tem um valor (offset) somado a elas. Por este motivo é fundamental fazer um processo de calibração, realizando leituras à medida que o módulo é girado e calculando o offset de cada eixo a partir delas.
Obtida a intensidade do campo magnético nos três eixos, a trigonometria nos permite obter o ângulo para o Norte magnético da Terra (no nosso exemplo vamos supor que o módulo está horizontal e portanto o eixo Z pode ser ignorado). O Norte magnético está ligeiramente afastado do Norte geográfico. Isto pode ser compensado através da declinação magnética, que pode ser consultada para a sua localidade neste site.
Para economizar energia, o chip inicialmente está num modo ocioso (sem realizar medições); ele pode ser configurado para diversas taxas de leitura do sensores. No nosso exemplo vamos usar o modo contínuo.
Montagem da bússola eletrônica com o módulo HMC5883L, anel de LEDs RGB e Arduino
A figura abaixo mostra a montagem que vamos usar. Para facilitar a montagem foi soldada uma barra de pinos 90 graus ao anel de LEDs. É importante o módulo bússola HMC5883L e o anel de LEDs RGB estarem alinhados como na figura.
Código
A maioria das bibliotecas disponíveis trata somente o HMC5883L; por este motivo escrevi rotinas específicas para o QMC5883L.
#include <Wire.h> // Classe simples para tratar a bússola class Bussola { public: Bussola(void); bool inicia(void); void setDeclination (int graus , int mins, char dir); int leDirecao(void); void iniciaCal(); void encerraCal(); private: static const int ender_QMC = 0x0D; // endereço I2C do QMC5883 static const int regCR1_QMC = 9; // registrador de configuração static const int regSR_QMC = 11; // registador set/reset static const int regXL_QMC = 0; // primeiro registrador de dados static const int regST_QMC = 6; // registrador de status // fatores de correção determinados na calibração int16_t xMin, yMin, xMax, yMax; float escX = 1.0; float escY = 1.0; int16_t offX = 0; int16_t offY = 0; // Diferença entre o Polo Magnético e o Geográfico float declination = 0.0; // Rotina para disparar leitura dos dados void pedeDados(int regStatus, int regDados); }; Bussola bussola; // Construtor Bussola::Bussola(void) { } // Inicia comunicação com a bússola bool Bussola::inicia() { // Confere o endereço Wire.beginTransmission(ender_QMC); if (Wire.endTransmission() != 0) { return false; } // Inicia o chip para modo contínuo Wire.beginTransmission(ender_QMC); Wire.write(regSR_QMC); Wire.write(0x01); Wire.endTransmission(); Wire.beginTransmission(ender_QMC); Wire.write(regCR1_QMC); Wire.write(0x0D); Wire.endTransmission(); return true; } // Define a declinação (correção entre o Norte magnético e o Norte geofráfico) // ver http://www.magnetic-declination.com/ void Bussola::setDeclination (int graus , int mins, char dir) { declination = (graus + mins / 60.0) * PI / 180.0; if (dir == 'W') { declination = - declination; } Serial.println (declination); } // Le a direção da bússola em graus (0 a 360) em relação à marcação do eixo X // Assume que a bússola esta na horizontal int Bussola::leDirecao(void) { int16_t x, y, z; // Le a intesidade do campo magnético pedeDados(regST_QMC, regXL_QMC); x = Wire.read(); //LSB x x |= Wire.read() << 8; //MSB x y = Wire.read(); //LSB y y |= Wire.read() << 8; //MSB y z = Wire.read(); //LSB z z |= Wire.read() << 8; //MSB z // Registra mínimo e máximo para a calibração if (x < xMin) { xMin = x; } if (xMax < x) { xMax = x; } if (y < yMin) { yMin = y; } if (yMax < y) { yMax = y; } // corrige e calcula o angulo em radianos float xC = (x - offX) * escX; float yC = (y - offY) * escY; float angulo = atan2 (yC, xC) + declination; // Garante que está entre 0 e 2*PI if (angulo < 0) { angulo += 2.0 * PI; } else if (angulo >= 2 * PI) { angulo -= 2.0 * PI; } // Converte para graus return round ((angulo * 180.0) / PI); } void Bussola::pedeDados(int regStatus, int regDados) { // Espera ter um dado a ler do { Wire.beginTransmission(ender_QMC); Wire.write(regStatus); Wire.endTransmission(); Wire.requestFrom(ender_QMC, 1); } while ((Wire.read() & 1) == 0); Wire.beginTransmission(ender_QMC); Wire.write(regDados); Wire.endTransmission(); Wire.requestFrom(ender_QMC, 6); } // Inicia processo de calibração void Bussola::iniciaCal() { xMax = yMax = -32768; xMin = yMin = 32767; } // Encerra a calibração void Bussola::encerraCal() { Serial.print ("X: "); Serial.print (xMin); Serial.print (" - "); Serial.println (xMax); Serial.print ("Y: "); Serial.print (yMin); Serial.print (" - "); Serial.println (yMax); // Offset para centralizar leituras em zero offX = (xMax + xMin) / 2; offY = (yMax + yMin) / 2; // Escala para ter a mesma variação nos dois eixos int16_t varX = xMax - xMin; int16_t varY = yMax - yMin; if (varY > varX) { escY = 1.0; escX = (float) varY / varX; } else { escX = 1.0; escY = (float) varX / varY; } }
Para controle do anel de LED vamos usar a biblioteca Adafruit NeoPixel, que você pode instalar direto do Gerenciador de Bibliotecas da IDE do Arduino:
Vamos usar o anel de LEDs para indicar a direção do Norte. Por exemplo, se o ângulo for exatamente 90 graus, vamos acender apenas o LED 3. Se o ângulo for 115 graus, vamos acender os LEDs 3 e 4 com igual intensidade. Se o ângulo for 100 graus, os LED 3 e 4 serão acesos, porém o LED 3 será aceso mais forte. A figura abaixo mostra a correspondência entre o índice do LED e o ângulo:
A rotina abaixo acende os LEDs apropriados:
#include <Adafruit_NeoPixel.h> const int PINO_ANEL = 3; const int IMAX = 63; // Intensidade máxima, 0 a 255 Adafruit_NeoPixel anel(12, PINO_ANEL, NEO_GRB + NEO_KHZ800); // Acende um ou dois LED do anel para indicar um ângulo // em relação ao eixo X do sensor // 0 <= angulo < 360 void aponta (int angulo) { // corrige o sentido angulo = 360 - angulo; if (angulo == 360) { angulo = 0; } // determina o primeiro LED int a = angulo / 30; a = (a + 10) % 12; // determina a intensidade do segundo LED int b = ((angulo % 30) * IMAX) / 30; // Acende os LEDs anel.clear(); anel.setPixelColor (a, anel.Color(0, IMAX - b, IMAX - b)); anel.setPixelColor ((a + 1) % 12, anel.Color(0, b, b)); anel.show(); }
Após iniciarmos bússola e LED, vamos realizar uma calibração por 20 segundos.
// Iniciação void setup() { // Inicia os LEDs anel.begin(); anel.clear(); // Inica a bussola Wire.begin(); Serial.begin(115200); if (!bussola.inicia()) { Serial.println ("Nao encontrou a bussola!"); for (;;) { delay(100); } } // Calibração da bussola Serial.println ("Calibrando... rode o sensor em um círculo"); int pos = 0; bussola.iniciaCal(); long tmpFim = millis() + 20000L; while (millis() < tmpFim) { bussola.leDirecao(); aponta (pos); pos += 5; if (pos == 360) { pos = 0; } delay (10); } bussola.encerraCal(); Serial.println ("Calibrado"); }
O programa principal lê a bússola e apresenta a direção do Norte nos LEDs.
// Laço principal void loop() { aponta(bussola.leDirecao()); delay (200); }
Colocando a bússola eletrônica com Arduino para funcionar
- Faça a montagem do circuito conforme a figura.
- Execute a IDE do Arduino no seu computador.
- Certifique-se que a placa selecionada no menu Ferramentas é o Arduino Nano.
- Conecte o Nano ao computador.
- Selecione no menu Ferramentas a porta onde o Nano está conectado.
- Copie (ou digite) o código acima (as quatro partes) em um novo sketch e salve com o nome “Bussola” (ou outro de sua preferência).
- Carregue o código no Arduino Nano.
- Após a carga (ou um reset do Arduino) os LEDs serão acesos sequencialmente de forma rápida, indicando que está sendo realizada a calibração. Gire a montagem para que o programa consiga registrar a leitura em todos os ângulos, procurando manter a protoboard paralela ao chão.
- Após 20 segundos a calibração será encerrada e os LEDs acesos passarão a indicar a direção do Norte magnético.
Resultado
Após a calibração, os LEDs acessos indicarão a direção do Norte magnético:
Conclusão
Usando o módulo Bússola Eletrônica HMC5883L podemos medir a direção para o Norte. Isto pode ser usado para fazer uma bússola (como neste projeto), descobrir a orientação do sensor ou até navegar um veículo robótico.
Agora que você já conhece o módulo Bússola Eletrônica HMC5883L e sabe como usá-lo, que tal testar algum projeto com ele?
Gostou do artigo “Construindo uma bússola eletrônica com o módulo HMC5883L, uma anel de LEDs RGB e um Arduino”? Deixe seu comentário logo abaixo dizendo o que achou. Para mais artigos e tutorias de projetos acesse nosso blog.
Muito bom!
Parabens!
Tem necessidade do arduíno ser o nano ?
Não, você pode usar outros modelos de Arduino, tomando o cuidado de usar os pinos corretos para as ligações.