巷で混同されているHMC5883LとQMC5883LですがQMC5883Lが主流になりつつあるので,
とりあえずHMC5883Lと思って間違えて買っちゃった方向けに,QMC5883Lの動作確認用に作りました.
最後のコードをこのままコピペして走らせると,CSVに保存されます.想定している環境はラズベリーパイです.
2024/05/21 追記
説明書見つけたので追記します
0x0Aに0x80を書き込むとリセットされるそうです.スケールは8Gに設定してるので,
出てきた値を3000で割ります.
参考記事
https://gujorobo.blogspot.com/2017/09/tj3bhmc5883lqmc5883l.html
https://github.com/RigacciOrg/py-qmc5883l/blob/master/py_qmc5883l/__init__.py
第一関門
そもそも認識されるか
sudo i2cdetect -y 1
認識されたら画像のように0x0dが表示されます.
いざ動作確認
import smbus2
import time
import csv
bus = smbus2.SMBus(1)
bus.write_byte_data(QMC5883L_ADDR, 0x0A, 0x80) #reset #5/21追記
bus.write_byte_data(QMC5883L_ADDR, 0x09, 0x1D) # define OSR=512,full scale range 8g odr 200hz
time.sleep(0.01) #5/21追記
def get_mag():
data = bus.read_i2c_block_data(QMC5883L_ADDR, QMC5883L_XOUT_L, 6)
x = data[0] | (data[1] << 8)
y = data[2] | (data[3] << 8)
z = data[4] | (data[5] << 8)
if x >= 32768:
x -= 65536
if y >= 32768:
y -= 65536
if z >= 32768:
z -= 65536
data=np.array([x,y,z])/3000 #8G: 3000LSB/G 2G:12000LSB/G #5/21追記
return data
with open('QMC5883test.csv', 'w', newline='') as file:
writer = csv.writer(file)
writer.writerow(['x','y','z'])
while True:
QMC5883_mag=QMC5883.get_mag()
print(QMC5883_mag)
writer.writerow([QMC5883_mag[0],QMC5883_mag[1],QMC5883_mag[2]])
平置きで一回転すると,xyでグラフを作ったときに円になるはずです.
キャリブレーションの1例として,最大値と最小値でオフセットする方法があります.
オフセットさせるとより正確なheading角が計算できると思います.
付録
グラフ作成は以下でやりました.
import csv
import matplotlib.pyplot as plt
import math
import numpy as np
# データを格納するリストを初期化
xx=[]
x = []
y = []
heading=[]
# CSVファイルを読み込む
with open('QMC5883test.csv', 'r') as file:
reader = csv.reader(file)
next(reader) # 1行目を無視
for row in reader:
x.append(float(row[0]))
y.append(float(row[1]))
heading.append(math.atan2(float(row[1]),float(row[0])))
x=np.array(x)
y=np.array(y)
maxx=max(x)
minx=min(x)
maxy=max(y)
miny=min(y)
shiftedx=[]
shiftedy=[]
shifted_heading=[]
for i in range(len(x)):
shiftedx.append(x[i]-(maxx+minx)/2)
shiftedy.append(y[i]-(maxy+miny)/2)
shifted_heading.append(math.atan2(shiftedy[i],shiftedx[i]))
heading = np.array(heading)
xx = range(len(heading))
# グラフを作成
plt.figure()
plt.plot(x, y, marker='o', linestyle='-',label='original')
plt.plot(shiftedx, shiftedy, marker='o', linestyle='-',label='shifted')
# タイトルとラベルの設定
plt.title('xy')
plt.xlabel('x(G)')
plt.ylabel('y(G)')
# 凡例を表示
plt.legend()
# 軸のスケールを等しくする
plt.axis('equal')
plt.grid(True)
# グラフを保存
plt.savefig('xy_shifted_graph.png')
# グラフを表示(オプション)
plt.show()
plt.figure()
plt.plot(xx, heading, marker='o', linestyle='-',label='original')
plt.plot(xx, shifted_heading, marker='o', linestyle='-',label='shifted')
# タイトルとラベルの設定
plt.title('heading')
plt.xlabel('row')
plt.ylabel('heading(rad)')
# 凡例を表示
plt.legend()
# グラフを保存
plt.savefig('heading_shifted_graph.png')
# グラフを表示(オプション)
plt.show()