概要
データシート
公式ライブラリ
Github
12bit DACの精度があるといっています。
自動的に、省エネモードになるみたいです。
矢印の方向的に、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を読み出すだけなら、特に設定もなく使える。
接続
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プロッタで表示すると
360度を2^12(4096)分割の精度なので、360/4096を掛ければ、角度に変換できます。
pinのDIRを5Vにすると、RAW ANGLEも方向が反転するみたいです。
感想
めっちゃ精度高いです。
磁石の上下位置は1mmぐらい上下しても、1度ぐらいしか変動しなかった(手の振動の影響かも)ので、上下方法は割とどこでもいい感じですね。
3.3V
3.3Vで運用する場合、VDD5Vと連結したほうがいいみたいです
右端の10μFは、OTP(one time programming)をする時のみ必要と書いてあります。
磁石について
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いかにする必要がある。
結構精度がいるな
軸方向のエアギャップは、磁石によって変化する。
ヒステリシスについて
ホールセンサはおそらく4つ乗っています。
磁石が回転すると、それぞれのセンサーは、S->N->S・・・と磁気が変化していきます。
計測される磁束密度は
こんな感じで変化します。
こんな感じに磁石とホールセンサを配置すると
磁束密度と磁石の位置xをの関係は
こんな感じになります。
曲線が二つあるのがわかります。
なぜこうなるかというと、私の予想ですが、磁石を近づけたことで、一部が磁化され、磁石を離しても、磁化された部分の影響で、磁石の磁力にプラスアルファされた磁場が発生し、実際よりも大きな磁場があると計測されるというわけです。
よって、回転角度に変換する際も、時計回りだったのを反時計回りで回すと、ヒステリシスが現れることになります。
Register mapの説明
スレーブアドレスは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)について
フィルターの設定
ノイズが少なく精度を上げるぶん、遅れが発生するみたい
Fast Filter は、FTHで設定した値を超えるぐらい、入力がばらつくときに発動する。
逆に、入力のばらつきが小さくなると、Slow Filterに切り替わる
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;
}