问题
I'm trying to plot data from mpu6050 imu with arduino. MPU6050 sends data faster than plot. Arduino code gives 6 data which are yaw, pitch, roll, ax,ay and az from serial port. I need suggestions for fast plot .
Python Code:
import serial
import matplotlib.pyplot as plt #import matplotlib library
from drawnow import *
ser = serial.Serial('COM9', 115200)
yaw = 0.0
pitch =0.0
roll =0.0
ax =0.0
ay =0.0
az =0.0
o_yaw= [0]
o_pitch= [0]
o_roll= [0]
o_ax= [0]
o_ay= [0]
o_az= [0]
plt.ion()
cnt=0
def makeFig():
plt.ylim(-1000,1000)
plt.grid(True)
plt.ylabel('Magnitude')
plt.plot(olculen_ax, 'ro-', label='ax')
plt.plot(olculen_ay, 'bo-', label='ay')
plt.plot(olculen_az, 'go-', label='az')
plt.legend()
while True:
incoming=ser.readline()
if ("hand" in incoming):
incoming=incoming.split(":")
if len(incoming)==8:
yaw = float(incoming[1])
pitch = float(incoming[2])
roll = float(incoming[3])
ax = float(incoming[4])
ay = float(incoming[5])
az = float(incoming[6])
print "Split works"
else:
print incoming
o_ax.append(ax)
o_ay.append(ay)
o_az.append(az)
o_yaw.append(yaw)
o_pitch.append(pitch)
o_roll.append(roll)
drawnow(makeFig)
plt.pause(.00001)
cnt=cnt+1
if(cnt>50):
o_ax.pop(0)
o_ay.pop(0)
o_az.pop(0)
Arduino Code (I just add loop. code derived from this):
void loop() {
if (!dmpReady) return;
while (!mpuInterrupt && fifoCount < packetSize) {
}
mpuInterrupt = false;
mpuIntStatus = mpu.getIntStatus();
fifoCount = mpu.getFIFOCount();
if ((mpuIntStatus & 0x10) || fifoCount == 1024) {
mpu.resetFIFO();
//Serial.println(F("FIFO overflow!"));
} else if (mpuIntStatus & 0x02) {
while (fifoCount < packetSize) fifoCount = mpu.getFIFOCount();
mpu.getFIFOBytes(fifoBuffer, packetSize);
fifoCount -= packetSize;
mpu.dmpGetQuaternion(&q, fifoBuffer);
mpu.dmpGetAccel(&aa, fifoBuffer);
mpu.dmpGetGravity(&gravity, &q);
mpu.dmpGetLinearAccel(&aaReal, &aa, &gravity);
mpu.dmpGetLinearAccelInWorld(&aaWorld, &aaReal, &q);
mpu.dmpGetYawPitchRoll(ypr, &q, &gravity);
Serial.print("hand:");
Serial.print(ypr[0] * 180/M_PI);
Serial.print(":");
Serial.print(ypr[1] * 180/M_PI);
Serial.print(":");
Serial.print(ypr[2] * 180/M_PI);
Serial.print(":");
Serial.print(aaWorld.x);
Serial.print(":");
Serial.print(aaWorld.y);
Serial.print(":");
Serial.print(aaWorld.z);
Serial.println(":");
}
}
回答1:
The pyqtgraph module is a great solution. It is very fast and easy.
Here is new code:
from pyqtgraph.Qt import QtGui, QtCore
import numpy as np
import pyqtgraph as pg
from pyqtgraph.ptime import time
import serial
app = QtGui.QApplication([])
p = pg.plot()
p.setWindowTitle('live plot from serial')
curve = p.plot()
data = [0]
raw=serial.Serial('COM9', 115200)
def update():
global curve, data
line = raw.readline()
if ("hand" in line):
line=line.split(":")
if len(line)==8:
data.append(float(line[4]))
xdata = np.array(data, dtype='float64')
curve.setData(xdata)
app.processEvents()
timer = QtCore.QTimer()
timer.timeout.connect(update)
timer.start(0)
if __name__ == '__main__':
import sys
if (sys.flags.interactive != 1) or not hasattr(QtCore, 'PYQT_VERSION'):
QtGui.QApplication.instance().exec_()
回答2:
Plotting real-time in Matplotlib? There's price to pay for all the power you are buying. Autoscaling, autoaxis, etc... It all costs time!
A much faster solution is using a toolkit such as Gtk, and doing the plotting yourself, with a canvas such as GooCanvas.
Still, there are a few things that you can do to speed up your plotting.
- Why the Pause statement?
- Split the communication to another thread and make the plot take the following sample when it's ready (skipping values from the input queue)
- You are appending, which makes the plot rescale frequently. Remove the first sample after N samples have been acquired.
- I believe it is possible to plot in the background with MatPlotLib (not sure) and then copy to the screen less frequently.
来源:https://stackoverflow.com/questions/31003837/fast-plotting-data-in-python