LoginSignup
0
0

QMC5883Lをpythonで使うための忘備録

Last updated at Posted at 2024-05-16

巷で混同されている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が表示されます.

スクリーンショット 2024-05-16 235346.png

いざ動作確認

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でグラフを作ったときに円になるはずです.
xy_graph.png

atan2を使えばheading角が出ます.
heading_graph.png

キャリブレーションの1例として,最大値と最小値でオフセットする方法があります.
オフセットさせるとより正確なheading角が計算できると思います.
xy_shifted_graph.png
heading_shifted_graph.png

付録

グラフ作成は以下でやりました.

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()
0
0
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
0
0