arduino 串口实时绘图(以mpu9250为例)

兴趣之余,利用晚上的时间,作一些我的兴趣方面的开发. 以前没接触过 arduino, 无心之中买了个开发板作一些小开发, 这里利用python 读取 mpu9250 数据实时绘图.python

 下位机代码 C++app

   
void Serial_SendDataPython( int16_t *sendData, uint8_t lens )
{
  uint8_t tmpData[32] = {0};  // tmpData lens >= 2 * lens + 4
  uint8_t *ptrData = tmpData;
  uint8_t dataBytes = lens << 1;
  uint8_t dataLens = dataBytes + 4;
  uint8_t count = 0;
  uint16_t tmpSum = 0;

  tmpData[0] = 'S';
  while(count < dataBytes) {
//    tmpData[count+1] = Byte8H(sendData[count >> 1]);
//    tmpData[count+2] = Byte8L(sendData[count >> 1]);

    tmpData[count+1] = (sendData[count >> 1])>>8;
    tmpData[count+2] = (sendData[count >> 1])&0x00ff; ;
    count = count + 2;
  }
  for(uint8_t i = 0; i < dataBytes; i++)
    tmpSum += tmpData[i+1];
  tmpData[dataLens - 3] = (uint8_t)(tmpSum & 0x00FF);
  tmpData[dataLens - 2] = '\r';
  tmpData[dataLens - 1] = '\n';

  do {
    //Serial_SendByte(*ptrData++);
    Serial.write(*ptrData++);
  } while(--dataLens);
}




....................................
 
IMU_Buf[0] = testLostRate++;
MU_Buf[1] = ax/2;
IMU_Buf[2] = ay/2;
IMU_Buf[3] = az/2;
IMU_Buf[4] = gx/2;
IMU_Buf[5] = gy/2;
IMU_Buf[6] = gz/2;
IMU_Buf[7] = mx/2;
IMU_Buf[8] = my/2;
IMU_Buf[9] = mz/2;
Serial_SendDataMATLAB(IMU_Buf, 10);

.................................................

 

这里简要说明一下, 发送数据以'S'开头,传感器数据分低8位和高8位数据分别发送,最后以换行符结尾.electron

  1 """
  2 ldr.py
  3 http://electronut.in/plotting-real-time-data-from-arduino-using-python/
  4 Display analog data from Arduino using Python (matplotlib)
  5 
  6 Author: Mahesh Venkitachalam
  7 Website: electronut.in
  8 """
  9 import ctypes
 10 import sys, serial, argparse
 11 import numpy as np
 12 from time import sleep
 13 from collections import deque
 14 
 15 import matplotlib.pyplot as plt 
 16 import matplotlib.animation as animation
 17 
 18     
 19 # plot class
 20 class AnalogPlot:
 21   # constr
 22   def __init__(self, strPort, maxLen):
 23       # open serial port
 24       self.ser = serial.Serial(strPort, 38400)
 25 
 26       self.ax = deque([0.0]*maxLen)
 27       self.ay = deque([0.0]*maxLen)
 28       self.az = deque([0.0]*maxLen)
 29       self.gx = deque([0.0]*maxLen)
 30       self.gy = deque([0.0]*maxLen)
 31       self.gz = deque([0.0]*maxLen)
 32       self.mx = deque([0.0]*maxLen)
 33       self.my = deque([0.0]*maxLen)
 34       self.mz = deque([0.0]*maxLen)  
 35       self.maxLen = maxLen
 36 
 37   # add to buffer
 38   def addToBuf(self, buf, val):
 39       if len(buf) < self.maxLen:
 40           buf.append(val)
 41       else:
 42           buf.pop()
 43           buf.appendleft(val)
 44 
 45   # add data
 46   def add(self, data):
 47       assert(len(data) == 9)
 48       self.addToBuf(self.ax, data[0])
 49       self.addToBuf(self.ay, data[1])
 50       self.addToBuf(self.az, data[2])
 51       self.addToBuf(self.gx, data[3])
 52       self.addToBuf(self.gy, data[4])
 53       self.addToBuf(self.gz, data[5])
 54       self.addToBuf(self.mx, data[6])
 55       self.addToBuf(self.my, data[7])
 56       self.addToBuf(self.mz, data[8])
 57   # update plot
 58   def update(self,frameNum,a0,a1,a2,a3,a4,a5,a6,a7,a8):
 59       try:
 60           data = self.ser.readline()
 61           length = len(data)
 62           if length == 24 and ord(data[0])== 83:
 63             count = (ord(data[1])<<8)+ord(data[2])
 64             value = (ord(data[3])<<8)+ord(data[4])
 65             ax = ctypes.c_int16(value).value
 66             value = (ord(data[5])<<8)+ord(data[6])
 67             ay = ctypes.c_int16(value).value
 68             value = (ord(data[7])<<8)+ord(data[8])
 69             az = ctypes.c_int16(value).value
 70             value = (ord(data[9])<<8)+ord(data[10])
 71             gx = ctypes.c_int16(value).value
 72             value = (ord(data[11])<<8)+ord(data[12])
 73             gy = ctypes.c_int16(value).value
 74             value = (ord(data[13])<<8)+ord(data[14])
 75             gz = ctypes.c_int16(value).value
 76             value = (ord(data[15])<<8)+ord(data[16])
 77             mx = ctypes.c_int16(value).value
 78             value = (ord(data[17])<<8)+ord(data[18])
 79             my = ctypes.c_int16(value).value
 80             value = (ord(data[19])<<8)+ord(data[20])
 81             mz = ctypes.c_int16(value).value
 82 
 83             array = [ax,ay,az,gx,gy,gz,mx,my,mz]
 84             print array
 85             self.add(array)
 86             a0.set_data(range(self.maxLen), self.ax)
 87             a1.set_data(range(self.maxLen), self.ay)
 88             a2.set_data(range(self.maxLen), self.az)
 89             a3.set_data(range(self.maxLen), self.gx)
 90             a4.set_data(range(self.maxLen), self.gy)
 91             a5.set_data(range(self.maxLen), self.gz)
 92             a6.set_data(range(self.maxLen), self.mx)
 93             a7.set_data(range(self.maxLen), self.my)
 94             a8.set_data(range(self.maxLen), self.mz)           
 95       except KeyboardInterrupt:
 96           print('exiting')
 97       
 98       return a0, 
 99 
100   # clean up
101   def close(self):
102       # close serial
103       self.ser.flush()
104       self.ser.close()    
105 
106 # main() function
107 def main():
108   # create parser
109   #parser = argparse.ArgumentParser(description="LDR serial")
110   # add expected arguments
111   #parser.add_argument('--port', dest='port', required=True)
112 
113   # parse args
114   #args = parser.parse_args()
115   
116   strPort = 'COM3'
117   #strPort = args.port
118 
119   print('reading from serial port %s...' % strPort)
120 
121   # plot parameters
122   analogPlot = AnalogPlot(strPort, 100)
123 
124   print('plotting data...')
125 
126   # set up animation
127   fig = plt.figure()
128   ax = plt.axes(xlim=(0, 100), ylim=(-20000, 20000))
129   a0, = ax.plot([], [])
130   a1, = ax.plot([], [])
131   a2, = ax.plot([], [])
132   a3, = ax.plot([], [])
133   a4, = ax.plot([], [])
134   a5, = ax.plot([], [])
135   a6, = ax.plot([], [])
136   a7, = ax.plot([], [])
137   a8, = ax.plot([], [])
138   anim = animation.FuncAnimation(fig, analogPlot.update, 
139                                  fargs=(a0,a1,a2,a3,a4,a5,a6,a7,a8), 
140                                  interval=50)
141 
142   # show plot
143   plt.show()
144   
145   # clean up
146   analogPlot.close()
147 
148   print('exiting.')
149   
150 
151 # call main
152 if __name__ == '__main__':
153   main()

 

运行结果以下图:工具

 

 

 从互联网搜索了一下,能够串口绘图的工具不少,试了一下 SerialChart工具,感受还不错,界面以下:测试

 

下位机数据格式较简单:网站

interval(两次数据获取时间间隔,可设置为0),ax,ay,az 为int 类型,ui

 

Serial.print(interval); //microseconds since last sample, please note that printing more data will increase interval
Serial.print(",");
Serial.print(ax); //Inclination X axis (as measured by accelerometer)
Serial.print(",");
Serial.print(ay); //Inclination X axis (estimated / filtered)
Serial.print(",");
Serial.print(az); //Inclination X axis (estimated / filtered)

Serial.println("");spa

具体使用方法请参见官方网站: https://en.wikiversity.org/wiki/SerialChart_Tutorial  ,这里有详细说明和配置方法.code

 

 

 

总结: 利用 python 读取seria 数据彷佛效率不怎么高, 和以前matlab 测试遇到的状况状况相似,容易出现卡顿的状况. 下篇博客我将会介绍数据可视化工具 Processing在这方便的用途和代码.blog

参考,引用:

http://electronut.in/plotting-real-time-data-from-arduino-using-python/

https://en.wikiversity.org/wiki/SerialChart_Tutorial

相关文章
相关标签/搜索