11
4

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

AS5600(磁気エンコーダー)をテストする

Last updated at Posted at 2021-12-05

概要

データシート

公式ライブラリ

Github

12bit DACの精度があるといっています。
自動的に、省エネモードになるみたいです。
16.png
矢印の方向的に、VDD(VCC)に5Vを入れて使うみたいです。3.3Vに3.3Vを入れても動くみたいです(3.3V mode)。

AGC:automatic gain control: adjust the amplification lelvel to compensate for temperature and magnetic field variations
AGCは、アンプの増幅率を、温度や周囲の磁気の変動に合わせて変化させます。

CORDICというシステムで、ホールセンサーの値を角度に変換します。
出力はPWMか、Analog出力かで選択可能のようです。

購入元

aliexpress で買いました。
磁石付きでよかった。300円ぐらいでした。

pinについて

pin 説明
DIR Ground->時計回り、VDD->反時計回り を正とする
PGO,GP0 Ground->Programming option B ,OTPをするためのモードっぽい
Analog output 角度
SDA A4
SCL A5
VCC 5.0V(6.1V以下)

ひとまず、実際に使ってみる

RAW ANGLEを読み出すだけなら、特に設定もなく使える。
IMG_20211205_163512175.jpg

接続

pin Arduino接続
DIR Ground-
PGO,GP0 接続しない
output 接続しない
SDA A4
SCL A5
VCC 5.0V
GND GND

サンプルプログラム

#include <Wire.h>

void setup() {
  Wire.begin();
  Serial.begin(250000);
}

void loop() {
  Wire.beginTransmission(0x36);
  Wire.write(0x0C);
  Wire.endTransmission(false);

  Wire.requestFrom(0x36, 2);

  while (Wire.available()) {
    byte angle_h = Wire.read();
    byte angle_l = Wire.read();
    unsigned int angle = (0x0F & angle_h) << 8 | angle_l;
    Serial.print(angle);
    //Serial.print(angle,HEX);
    Serial.print(" ");
  }
  delay(1);


  Wire.beginTransmission(0x36);
  Wire.write(0x0B);
  Wire.endTransmission(false);

  Wire.requestFrom(0x36, 1);

  while (Wire.available()) {
    byte state = Wire.read();
    
    Serial.println(state, BIN);
  }
  
}

二個データがSerialプロッタに入ってきます。
最初の一個目は角度データ。二個目は状態情報

1100111 => 正常
1001111 => 磁力強すぎ
1010111 => 磁力弱すぎ

という意味です。

結果

二個目のstateデータの送信を停止し、Serialプロッタで表示すると

27.png
いい感じで変換されてます。

360度を2^12(4096)分割の精度なので、360/4096を掛ければ、角度に変換できます。

pinのDIRを5Vにすると、RAW ANGLEも方向が反転するみたいです。

感想

めっちゃ精度高いです。
磁石の上下位置は1mmぐらい上下しても、1度ぐらいしか変動しなかった(手の振動の影響かも)ので、上下方法は割とどこでもいい感じですね。

3.3V

17.png

3.3Vで運用する場合、VDD5Vと連結したほうがいいみたいです
右端の10μFは、OTP(one time programming)をする時のみ必要と書いてあります。

磁石について

19.png
Bz:おそらく、z軸方向の磁束密度
図の黄色の円に注目してほしい、この領域は、傾きが一定な平面である。このセンサーはこの特徴をもとに角度を計算する。

「The maximum allowed displacement of the rotational
axis of the reference magnet from the center of the package is
0.25 mm when using a magnet with a diameter of 6mm.」
6mmの磁石を使う場合、センサーの中心軸からの磁石の回転軸のずれは0.25mmいかにする必要がある。

結構精度がいるな

20.png
中心の直径1mmの円にホールセンサーを配置してるそうです。

軸方向のエアギャップは、磁石によって変化する。

ヒステリシスについて

ホールセンサはおそらく4つ乗っています。
磁石が回転すると、それぞれのセンサーは、S->N->S・・・と磁気が変化していきます。
計測される磁束密度は
21.png
こんな感じで変化します。

仮に、
22.png

こんな感じに磁石とホールセンサを配置すると
磁束密度と磁石の位置xをの関係は
24.png
こんな感じになります。
曲線が二つあるのがわかります。
なぜこうなるかというと、私の予想ですが、磁石を近づけたことで、一部が磁化され、磁石を離しても、磁化された部分の影響で、磁石の磁力にプラスアルファされた磁場が発生し、実際よりも大きな磁場があると計測されるというわけです。

よって、回転角度に変換する際も、時計回りだったのを反時計回りで回すと、ヒステリシスが現れることになります。

Register mapの説明

18.png

スレーブアドレスは0x36です。

ZPOS: start position
MPOS: stop position
MANG: maximum angle
ZMCO: 何回、永久書き込みが行われたかを示す。3回まで

角度範囲を狭めると精度が上がる。
範囲は18度以上でないと、精度の向上にはならない。18度以下にしてはいけない。

0x07

bit 説明
PM(2bit) 0:normal ,01:LPM1,10:LPM2,11:LPM3 LPM= low power mode,磁気計測の間隔が変わるらしい
HYST(2bit) 0:OFF,01:1 LSB,10:2 LSB,11:3 LSB、シュミッドトリガがあるみたい
OUTS(2bit) 10:PWM出力,00:analog(0~100%),01:analog(10~90%),11? ,I2Cで読み出す場合はどちらでも関係ない
PWMF PWMの周波数 00:115Hz,01:230Hz,10:460Hz,11:920Hz

SF(Slow Filter),FTH(Fast Filter Threshold,3bit)について

フィルターの設定
25.png
ノイズが少なく精度を上げるぶん、遅れが発生するみたい

Fast Filter は、FTHで設定した値を超えるぐらい、入力がばらつくときに発動する。
逆に、入力のばらつきが小さくなると、Slow Filterに切り替わる
26.png

STATUS

bit 説明
MH 1=磁力が強すぎる
ML 1=磁力が弱すぎる
MD 1=磁石があることを検知

Programming mode

以降、いくつか永久書き込みについて説明しますが、何に使うかまず説明します。
この角度センサーは原理的に絶対位置がわかります。
よって、初期位置は0度ではありません。

初期位置でRAW ANGLEを読み込み
ZPOSに格納すれば、初期位置が0度になります。

B mode

OUT pinで設定の書き換えを行う
一度しか行えない、永久書き込みになる、注意

start position と stop position をPG0(GP0)をGNDにすることで教える。

A mode

I2Cで設定の書き換えを行う
ZPOS,MPOSをRAW ANGLEを読み込み、書き込むことで使用する。

以下は永久書き込みする場合の手順

  • BURN_ANGLE(0x80)をBURN Register(0xFF)に書き込む
  • 0.1ms待って、
  • 0x01,0x11,0x10をBURN Register(0xFF)に書き込む

ことで、永久書き込みができる

3回しかできないので注意

C mode

Aと違い、MANGとZPOSを永久書き込みする場合の手順

まず、

  • MANGに角度範囲を書き込む
  • CONFIGも書き込む
  • BURN_SETTINGS(0x40)をBURN Register(0xFF)に書き込む
  • 0x01,0x11,0x10をBURN Register(0xFF)に書き込む
  • ZPOSを書き込む

Burn angle command

ZPOS,MPOSの永久書き込みに使用
3回まで行える。
ZMCOが一回ごとに増えていく

Burn setting command

MANGを永久書き込みするのに使う
ZMCO=0の時のみ使用可能
一度のみ可能

磁石とセンサーを動かさないと確定したら、実行する
これをしない場合、使うたびに、初めに磁石の位置を教える必要がある。

ZPOS,MPOSを読み込んでみる

デフォルトでは

ZPOS = 0xFOF
MPOS = 0x000
RAW ANGLE = 0x46B
ANGLE = 0x46B

でした。

ZPOSにRAW ANGLEで書き換えてみます。

ZPOS = 4003
MPOS = 4003
RAW ANGLE = 4003
ANGLE = 0

となりました。
ZPOSを書き換えるだけで、自動的にMPOSが書き換わるようです。
さらに、ANGLEも0にずれました。初期位置の設定がこれで行えます。

永久書き込みについては、怖いうえに、今のところ必要そうでないので、チェックはしません。

プログラム

#include <Wire.h>
unsigned int AS5600_read_2byte(byte address);
byte AS5600_read(byte address);
void AS5600_write(byte address,byte data);

void setup() {
  Wire.begin();
  Serial.begin(250000);
  
  byte data1;
  byte data2;
  data1 = AS5600_read(0x0C);
  data2 = AS5600_read(0x0D);

  AS5600_write(0x01,data1);
  AS5600_write(0x02,data2);
  
  
}

void loop() {
  unsigned int raw_angle;
  raw_angle = AS5600_read_2byte(0x0C);      //RAW agle
  delay(100);

  unsigned int angle;
  angle = AS5600_read_2byte(0x0E);      //agle
  delay(100);

  unsigned int zpos;
  zpos = AS5600_read_2byte(0x01);      //ZPOS
  delay(100);

  unsigned int mpos;
  mpos = AS5600_read_2byte(0x03);      //MPOS
  delay(100);

  Serial.print(raw_angle);
  Serial.print(" ");
  Serial.print(angle);
  Serial.print(" ");
  Serial.print(zpos);
  Serial.print(" ");
  Serial.print(mpos);
  Serial.println(" ");
  
}

void AS5600_write(byte address,byte data){
  Wire.beginTransmission(0x36);
  Wire.write(address);
  Wire.write(data);  
  Wire.endTransmission();
}

byte AS5600_read(byte address){
  Wire.beginTransmission(0x36);
  Wire.write(address);
  Wire.endTransmission(false);

  Wire.requestFrom(0x36, 1);

  byte data;
  while (Wire.available()) {
    data = Wire.read();
  }
  return data;
}

unsigned int AS5600_read_2byte(byte address){
  Wire.beginTransmission(0x36);
  Wire.write(address);
  Wire.endTransmission(false);

  Wire.requestFrom(0x36, 2);
  unsigned int mpos;
  while (Wire.available()) {
    byte mpos_h = Wire.read();
    byte mpos_l = Wire.read();
    mpos = (0x0F & mpos_h) << 8 | mpos_l;
  }
  return mpos;
}


11
4
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
11
4

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?