//
表示中
モノづくり, Bicycle - 自転車, Computer - コンピューター, Electronics - 電子工作, Music - 音楽

L3GD20ジャイロセンサーの動作確認


今日は3日ぶりくらいにエレキギターの漆塗装をやりました。前回とあまり変わりばえがしないので記事にしてもつまらないのですが、一応、これが主軸の作業なので、やっているぞ!ということをアピールしておきます。笑

目止めはしたものの、がっつりと漆を厚塗りをする塗装方法ではないので、なかなか塗装面が平らになりません。漆以外のもので下地を作るという手もあるにはありますが、時間がかかっても全部漆で通そうと思います。

2016-03-10 09.39.09

2016-03-10 09.54.45

 

ギター製作の合間にやっている電子工作の勉強。

今日は3軸ジャイロセンサーL3GD20というものを扱いました。ストロベリーリナックスさんから購入したものです。

2016-03-10 10.37.28

説明書を見ながらArduinoと接続した回路を組みました。前回GPS受信機の動作確認を行った時に組んだブレッドボードの回路を少し修正してL3GD20を共存させるような形にしました。

2016-03-10 11.04.46

近づいて撮った写真。これを見てもどこがどこにつながっているのかがわからないと思いますが、製品に同封されていた説明書通りに配線をしたので、説明書を見ながらこの写真を見ると多少はわかりやすいかもしれません。

2016-03-10 11.05.20

L3GD20を扱うライブラリがここにありましたので、それを一部自分の環境に合わせて手直しをして使いました。このセンサーはI2C(アイ・スクエア・C)という方法かSPIという方法でマイコンと通信ができるもので、今回はI2C方式でやりました。

試験用のプログラムはこんな感じです。L3GD20.hとL3GD20.cppというタブが見えますが、これらが前述のライブラリを手直ししたものです。

L3GD20_Test

こちらは実行結果。センサーを載せたブレッドボードを手に持って動かすとX、Y、Z軸の値が変化するのがわかります。

L3GD20_Result

通称「坂バカ」と呼ばれる坂が大好きなロードバイク乗りが、自分がどれくらいの勾配の坂を登っているのかを見ながらニヤニヤできるような機器になるかもしれません。

以下に今回若干手を入れて使ったL3GD20用のライブラリです。I2CとSPIのどちらにも対応したライブラリでとても使いやすいです。

L3GD20.h

 

/*************************************************** 
  This is an example for the Adafruit Triple-Axis Gyro sensor
  Designed specifically to work with the Adafruit L3GD20 Breakout 
  ----> https://www.adafruit.com/products/1032
  These sensors use I2C or SPI to communicate, 2 pins (I2C) 
  or 4 pins (SPI) 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 "KTOWN" Townsend for Adafruit Industries.  
  BSD license, all text above must be included in any redistribution
 ****************************************************/

/***************************************************
 * Changed class name (my favor) and some definitions (for my use)
 ***************************************************/
 
#ifndef _L3GD20_h
#define _L3GD20_h

#if (ARDUINO >= 100)
  #include "Arduino.h"
#else
  #include "WProgram.h"
#endif

#include "Wire.h"

//#define L3GD20_ADDRESS                (0x6B)      // 1101011 (if SA0 connected to VDD_IO)
#define L3GD20_ADDRESS                (0x6A)        // 1101010 (if SA0 connected to GND)
#define L3GD20_POLL_TIMEOUT           (100)         // Maximum number of read attempts
#define L3GD20_ID                     0xD4
#//define L3GD20H_ID                    0xD7

#define L3GD20_SENSITIVITY_250DPS  (0.00875F)      // Roughly 22/256 for fixed point match
#define L3GD20_SENSITIVITY_500DPS  (0.0175F)       // Roughly 45/256
#define L3GD20_SENSITIVITY_2000DPS (0.070F)        // Roughly 18/256
#define L3GD20_DPS_TO_RADS         (0.017453293F)  // degress/s to rad/s multiplier

class L3GD20
{
  public:
    typedef enum
    {
      L3GD20_REGISTER_WHO_AM_I            = 0x0F,   // 11010100   r
      L3GD20_REGISTER_CTRL_REG1           = 0x20,   // 00000111   rw
      L3GD20_REGISTER_CTRL_REG2           = 0x21,   // 00000000   rw
      L3GD20_REGISTER_CTRL_REG3           = 0x22,   // 00000000   rw
      L3GD20_REGISTER_CTRL_REG4           = 0x23,   // 00000000   rw
      L3GD20_REGISTER_CTRL_REG5           = 0x24,   // 00000000   rw
      L3GD20_REGISTER_REFERENCE           = 0x25,   // 00000000   rw
      L3GD20_REGISTER_OUT_TEMP            = 0x26,   //            r
      L3GD20_REGISTER_STATUS_REG          = 0x27,   //            r
      L3GD20_REGISTER_OUT_X_L             = 0x28,   //            r
      L3GD20_REGISTER_OUT_X_H             = 0x29,   //            r
      L3GD20_REGISTER_OUT_Y_L             = 0x2A,   //            r
      L3GD20_REGISTER_OUT_Y_H             = 0x2B,   //            r
      L3GD20_REGISTER_OUT_Z_L             = 0x2C,   //            r
      L3GD20_REGISTER_OUT_Z_H             = 0x2D,   //            r
      L3GD20_REGISTER_FIFO_CTRL_REG       = 0x2E,   // 00000000   rw
      L3GD20_REGISTER_FIFO_SRC_REG        = 0x2F,   //            r
      L3GD20_REGISTER_INT1_CFG            = 0x30,   // 00000000   rw
      L3GD20_REGISTER_INT1_SRC            = 0x31,   //            r
      L3GD20_REGISTER_TSH_XH              = 0x32,   // 00000000   rw
      L3GD20_REGISTER_TSH_XL              = 0x33,   // 00000000   rw
      L3GD20_REGISTER_TSH_YH              = 0x34,   // 00000000   rw
      L3GD20_REGISTER_TSH_YL              = 0x35,   // 00000000   rw
      L3GD20_REGISTER_TSH_ZH              = 0x36,   // 00000000   rw
      L3GD20_REGISTER_TSH_ZL              = 0x37,   // 00000000   rw
      L3GD20_REGISTER_INT1_DURATION       = 0x38    // 00000000   rw
    } L3GD20Register;

    typedef enum
    {
      L3GD20_RANGE_250DPS,
      L3GD20_RANGE_500DPS,
      L3GD20_RANGE_2000DPS
    } L3GD20Range;

    typedef struct l3gd20Data_s
    {
      float x;
      float y;
      float z;
    } L3GD20Data;

    L3GD20(int8_t cs, int8_t mosi, int8_t miso, int8_t clk);
    L3GD20(void);

    bool begin(L3GD20Range r=L3GD20_RANGE_250DPS, byte addr=L3GD20_ADDRESS);
    void read(void);

    L3GD20Data data;

  private:
    void write8(L3GD20Register reg, byte value);
    byte read8(L3GD20Register reg);
    uint8_t SPIxfer(uint8_t x);
    byte address;
    L3GD20Range range;
    int8_t _miso, _mosi, _clk, _cs;
};

#endif

 

L3GD20.cpp

#include "L3GD20.h"

L3GD20::L3GD20(int8_t cs, int8_t miso, int8_t mosi, int8_t clk) {
  _cs = cs;
  _miso = miso;
  _mosi = mosi;
  _clk = clk;
}

L3GD20::L3GD20(void) {
  // user i2c
  _cs = _mosi = _miso = _clk = -1;
}

bool L3GD20::begin(L3GD20Range r, byte addr) {
  if(_cs == -1) {
    Wire.begin();
  } else {
    pinMode(_cs, OUTPUT);
    pinMode(_clk, OUTPUT);
    pinMode(_mosi, OUTPUT);
    pinMode(_miso, INPUT);
    digitalWrite(_cs, HIGH);
  }

  address = addr;
  range = r;

  // Ask if it is L3G20
  uint8_t id = read8(L3GD20_REGISTER_WHO_AM_I);
  if(id != L3GD20_ID) {
    return false;
  }

  // Enabling GYRO
  write8(L3GD20_REGISTER_CTRL_REG1, 0x0F);

  // Adjust resolution range
  switch(range) {
    case L3GD20_RANGE_250DPS:
      write8(L3GD20_REGISTER_CTRL_REG4, 0x00);
      break;
    case L3GD20_RANGE_500DPS:
      write8(L3GD20_REGISTER_CTRL_REG4, 0x10);
      break;
    case L3GD20_RANGE_2000DPS:
      write8(L3GD20_REGISTER_CTRL_REG4, 0x20);
      break;
    default:
      break;
  }

  return true;   
}

void L3GD20::read() {
  uint8_t xhi, xlo, ylo, yhi, zlo, zhi;

  if(_cs == -1) {
    // i2c
    Wire.beginTransmission(address);
    Wire.write(L3GD20_REGISTER_OUT_X_L | 0x80);
    Wire.endTransmission();
    Wire.requestFrom(address, (byte)6);
    while(Wire.available() < 6) ;
    xlo = Wire.read();
    xhi = Wire.read();
    ylo = Wire.read();
    yhi = Wire.read();
    zlo = Wire.read();
    zhi = Wire.read();
  } else {
    // spi
    digitalWrite(_clk, HIGH);
    digitalWrite(_cs, LOW);
    SPIxfer(L3GD20_REGISTER_OUT_X_L | 0x80 | 0x40);
    delay(20);
    xlo = SPIxfer(0xFF);
    xhi = SPIxfer(0xFF);
    ylo = SPIxfer(0xFF);
    yhi = SPIxfer(0xFF);
    zlo = SPIxfer(0xFF);
    zhi = SPIxfer(0xFF);
    digitalWrite(_cs, HIGH);
  }

  data.x = (int16_t)(xlo | (xhi << 8));
  data.y = (int16_t)(ylo | (yhi << 8));
  data.z = (int16_t)(zlo | (zhi << 8));   
  switch(range) {     
    case L3GD20_RANGE_250DPS:       
      data.x *= L3GD20_SENSITIVITY_250DPS;       
      data.y *= L3GD20_SENSITIVITY_250DPS;       
      data.z *= L3GD20_SENSITIVITY_250DPS;       
      break;     
    case L3GD20_RANGE_500DPS:       
      data.x *= L3GD20_SENSITIVITY_500DPS;       
      data.y *= L3GD20_SENSITIVITY_500DPS;       
      data.z *= L3GD20_SENSITIVITY_500DPS;       
      break;     
    case L3GD20_RANGE_2000DPS:       
      data.x *= L3GD20_SENSITIVITY_2000DPS;       
      data.y *= L3GD20_SENSITIVITY_2000DPS;       
      data.z *= L3GD20_SENSITIVITY_2000DPS;       
      break;   
  } 
} 

void L3GD20::write8(L3GD20Register reg, byte value) {   
  if(_cs == -1) {     
    // i2c
    Wire.beginTransmission(address);     
    Wire.write((byte)reg);     
    Wire.write(value);     
    Wire.endTransmission();   
  } else {     
    // spi     
    digitalWrite(_clk, HIGH);     
    digitalWrite(_cs, LOW);     
    SPIxfer(reg);     
    SPIxfer(value);     
    digitalWrite(_cs, HIGH);   
  } 
} 

byte L3GD20::read8(L3GD20Register reg) {   
  byte value;   
  if(_cs == -1) {     
    // i2c     
    Wire.beginTransmission(address);     
    Wire.write((byte)reg);     
    Wire.endTransmission();     
    Wire.requestFrom(address, (byte)1);     
    value = Wire.read();     
    Wire.endTransmission();   
  } else {     
    // spi     
    digitalWrite(_clk, HIGH);     
    digitalWrite(_cs, LOW);     
    SPIxfer((uint8_t)reg | 0x80);     
    value = SPIxfer(0xFF);     
    digitalWrite(_cs, HIGH);   
  }   
  return value; 
} 

uint8_t L3GD20::SPIxfer(uint8_t x) {   
  uint8_t value = 0;   
  for(int i = 7; i >= 0; i--) {
    digitalWrite(_clk, LOW);
    if(x & (1<<i)) {
      digitalWrite(_mosi, HIGH);
    } else {
      digitalWrite(_mosi, LOW);
    }
    digitalWrite(_clk, HIGH);
    if(digitalRead(_miso)) {
      value |= (1<<i);
    }
  }
  return value;
}

kazz12211 について

Working as a OO programmer and enjoying music, bicycle and photography.

ディスカッション

コメントはまだありません。

コメントを残す

以下に詳細を記入するか、アイコンをクリックしてログインしてください。

WordPress.com ロゴ

WordPress.com アカウントを使ってコメントしています。 ログアウト / 変更 )

Twitter 画像

Twitter アカウントを使ってコメントしています。 ログアウト / 変更 )

Facebook の写真

Facebook アカウントを使ってコメントしています。 ログアウト / 変更 )

Google+ フォト

Google+ アカウントを使ってコメントしています。 ログアウト / 変更 )

%s と連携中

評価

ブログ統計

  • 589,534 ヒット

カテゴリー

アーカイブ

カレンダー

2016年3月
« 2月   4月 »
 12345
6789101112
13141516171819
20212223242526
2728293031  
%d人のブロガーが「いいね」をつけました。