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

相關文章
相關標籤/搜索