メインコンテンツに移動

GR-ADZUKI 特設:デジタルコンパスで遊ぶ!

概要

GR-ADZUKIにデジタルコンパスを搭載して方角を調べてみましょう!


準備

ハードウェア

GR-ADZUKI、USBケーブル(マイクロBタイプ)、HMC5883Lデジタルコンパスを用意してください。

デジタルコンパスを以下のように接続してください。GR-ADZUKIのスライドスイッチの下側が[ Sketch ]になっていることを確認してください。

gr-adzuki-sp-connect-digitalcompass


ソフトウェア

デジタルコンパスはS4Aで使用できないため、ここではWebコンパイラを使用します。Webコンパイラの基本的な使い方は 「Webコンパイラでスケッチ」を参照してください。

また、IDE for GRでもお試し可能です。IDE for GRの基本的な使い方については「IDE for GRでArduinoスケッチ!」を参照してください。

gr-adzuki-board
usb-cable

digital-compass-hmc5883l


HMC5883L用ライブラリのインポート

Adafruitのライブラリを使います。以下のリンクからzipに圧縮された2つのライブラリをダウンロードしてください。

WebコンパイラでGR-ADZUKIのプロジェクトを作成後、プロジェクトのルートからアップロードを行います。zipファイルのままアップロードしてください。

なお、IDE for GRでもライブラリをインポートできますが、library.propertiesというファイルを削除してからインポートしてください。削除しないと「Missing 'core-dependencies' from library」というエラーが発生します。

GR-ADZUKIデジタルコンパスライブラリファイルアップロード

2つのライブラリをアップロードすると以下のようにプロジェクトツリーに表示されます。

GR-ADZUKIデジタルコンパスライブラリ2ファイルアップロード


サンプルプログラム

以下のようにプロジェクトツリーのAdafruit_HMC5883_Unifiedフォルダのexamplesにあるmagsensor.inoを開き、すべてをコピーします。

gr-adzuki-sp-digitalcompass-library-example-magsensor

以下のようにgr_sketch.cppを開き、#include<Arduino.h>の下にペーストしてください。

gr-adzuki-sp-digitalcompass-library-example2-gr-sketch-cpp

ビルド実行後、adzuki_sketch.binファイルをGR-ADZUKIに書き、シリアルモニターで出力を確認してみましょう。以下のようにX,Y,Zの磁束密度(uT:テスラ)と、X,Yから求めた方位角が表示されます。

gr-adzuki-sp-digitalcompass-library-example3-sketch-bin-file

上の図の例では359.51になっていますが、HMC5883LのXがほぼ北に向いていることを示しています。

gr-adzuki-sp-digitalcompass2


センサー出力のタイミングを考慮する

HMC5883Lはセンサー出力の準備ができたタイミングで、以下のようにDRDY信号にパルスを発生します。約65ms間隔のパルスが確認できます。

gr-adzuki-sp-digitalcompass-signal

GR-ADZUKIのINT2(ピン25)を使用して、このパルスに合わせてセンサーの値を取得することができます。以下はサンプルプログラムです。実行すると方位角が出力されます。


/*GR-ADZUKI Sketch Template Version: V2.01*/
#include <Arduino.h>
/***************************************************************************
  This is a library example for the HMC5883 magnentometer/compass
 
  Designed specifically to work with the Adafruit HMC5883 Breakout
  http://www.adafruit.com/products/1746
 
  *** You will also need to install the Adafruit_Sensor library! ***
 
  These displays use I2C to communicate, 2 pins are required to interface.
 
  Adafruit invests time and resources providing this open source code,
  please support Adafruit and open-source hardware by purchasing products
  from Adafruit!
 
  Written by Kevin Townsend for Adafruit Industries with some heading example from
  Love Electronics (loveelectronics.co.uk)
 
 This program is free software: you can redistribute it and/or modify
 it under the terms of the version 3 GNU General Public License as
 published by the Free Software Foundation.
 
 This program is distributed in the hope that it will be useful,
 but WITHOUT ANY WARRANTY; without even the implied warranty of
 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 GNU General Public License for more details.
 
 You should have received a copy of the GNU General Public License
 along with this program.  If not, see <http://www.gnu.org/licenses/>.
 
 ***************************************************************************/
 
#include <Wire.h>
#include <Adafruit_Sensor.h>
#include <Adafruit_HMC5883_U.h>
 
/* Assign a unique ID to this sensor at the same time */
Adafruit_HMC5883_Unified mag = Adafruit_HMC5883_Unified(12345);
bool g_sensor_flag;
 
void displaySensorDetails(void)
{
  sensor_t sensor;
  mag.getSensor(&sensor);
  Serial.println("------------------------------------");
  Serial.print  ("Sensor:       "); Serial.println(sensor.name);
  Serial.print  ("Driver Ver:   "); Serial.println(sensor.version);
  Serial.print  ("Unique ID:    "); Serial.println(sensor.sensor_id);
  Serial.print  ("Max Value:    "); Serial.print(sensor.max_value); Serial.println(" uT");
  Serial.print  ("Min Value:    "); Serial.print(sensor.min_value); Serial.println(" uT");
  Serial.print  ("Resolution:   "); Serial.print(sensor.resolution); Serial.println(" uT");
  Serial.println("------------------------------------");
  Serial.println("");
  delay(500);
}
 
void sensor_rdy(){
  digitalWrite(10, HIGH);
  g_sensor_flag = true;
}
 
void setup(void)
{
  Serial.begin(9600);
  Serial.println("HMC5883 Magnetometer Test"); Serial.println("");
 
  pinMode(25, INPUT_PULLUP);
  attachInterrupt(2, sensor_rdy, FALLING);
  g_sensor_flag = false;
 
  /* Initialise the sensor */
  if(!mag.begin())
  {
    /* There was a problem detecting the HMC5883 ... check your connections */
    Serial.println("Ooops, no HMC5883 detected ... Check your wiring!");
    while(1);
  }
 
  /* Display some basic information on this sensor */
  displaySensorDetails();
}
 
void loop(void)
{
  /* Get a new sensor event */
  if(g_sensor_flag == true){
    sensors_event_t event;
    mag.getEvent(&event);
     
    float heading = atan2(event.magnetic.y, event.magnetic.x);
    if(heading < 0) heading += 2*PI;
    if(heading > 2*PI) heading -= 2*PI;
    float headingDegrees = heading * 180/M_PI;
    Serial.print("Heading (degrees): "); Serial.println(headingDegrees);
    g_sensor_flag = false;
  }
}