In this video lesson we create a PyQt5 Widget in Python to help calibrate the QMC5883L 3-Axis Magnetometer on the GY-87 module. The Widget plots the data coming from the Magnetometer in real time to allow more accurate calibration.
This is the circuit schematic for our project:

This is the simple code for the arduino to generate the raw data;
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 | #include <Adafruit_MPU6050.h> #include <Adafruit_Sensor.h> #include <Wire.h> #include <QMC5883LCompass.h> int x,y,z; Adafruit_MPU6050 mpu; QMC5883LCompass compass; void setup() { Serial.begin(115200); mpu.begin(); mpu.setI2CBypass(true); compass.init(); } void loop() { compass.read(); x = compass.getX(); y = compass.getY(); z = compass.getZ(); Serial.print(x); Serial.print(','); Serial.print(y); Serial.print(','); Serial.println(z); delay(100); } |
This is the code we run on the Python side to plot the raw data:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 | import serial import numpy as np from PyQt5 import QtWidgets, QtCore import pyqtgraph as pg serialPort = 'COM8' baudRate =115200 to =.1 ser =serial.Serial(serialPort, baudRate, timeout=to) maxPoints = 2000 xRaw = np.empty(0) yRaw = np.empty(0) zRaw = np.empty(0) app = QtWidgets.QApplication([]) mainWindow = QtWidgets.QWidget() mainWindow.setWindowTitle("Magnetometer Calibratioin") mainLayout =QtWidgets.QVBoxLayout() mainWindow.setLayout(mainLayout) plotLayout =QtWidgets.QGridLayout() mainLayout.addLayout(plotLayout) xyPlot = pg.PlotWidget(title="XY Plane") yzPlot = pg.PlotWidget(title="YZ Plane") xzPlot = pg.PlotWidget(title="XZ Plane") for plot in [xyPlot, yzPlot, xzPlot]: plot.setAspectLocked(True) plot.showGrid(x=True, y=True) plot.setMinimumSize(300,300) plotLayout.addWidget(xyPlot, 0,0) plotLayout.addWidget(yzPlot, 0,1) plotLayout.addWidget(xzPlot, 1,0) xyScatter = pg.ScatterPlotItem(size=5) yzScatter = pg.ScatterPlotItem(size=5) xzScatter = pg.ScatterPlotItem(size=5) xyPlot.addItem(xyScatter) yzPlot.addItem(yzScatter) xzPlot.addItem(xzScatter) def updatePlot(): global xRaw, yRaw, zRaw if ser.in_waiting > 0: try: line= ser.readline().decode('utf-8').strip() print(line) values = line.split(',') if len(values)==3: x = float(values[0]) y = float(values[1]) z = float(values[2]) xRaw =np.append(xRaw, x)[-maxPoints:] yRaw =np.append(yRaw, y)[-maxPoints:] zRaw =np.append(zRaw, z)[-maxPoints:] xyScatter.setData(x=xRaw, y=yRaw, brush=pg.mkBrush(0,0,255,120)) yzScatter.setData(x=yRaw, y=zRaw, brush=pg.mkBrush(0,255,0,120)) xzScatter.setData(x=xRaw, y=zRaw, brush=pg.mkBrush(255,0,0,120)) except Exception as e: print("Parse Error: ", e) plotTimer =QtCore.QTimer() plotTimer.timeout.connect(updatePlot) plotTimer.start(50) mainWindow.show() try: app.exec_() finally: ser.close() |