arduino 串口實時繪圖(以mpu9250為例)


興趣之余,利用晚上的時間,做一些個人興趣方面的開發. 之前沒接觸過 arduino, 無意之中買了個開發板做一些小開發, 這里利用python 讀取 mpu9250 數據實時繪圖.

 下位機代碼 C++

   
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位數據分別發送,最后以換行符結尾.

  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 類型,

 

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("");

具體使用方法請參見官方網站: https://en.wikiversity.org/wiki/SerialChart_Tutorial  ,這里有詳細說明和配置方法.

 

 

 

總結: 利用 python 讀取seria 數據似乎效率不怎么高, 和之前matlab 測試遇到的情況情況類似,容易出現卡頓的情況. 下篇博客我將會介紹數據可視化工具 Processing在這方便的用途和代碼.

參考,引用:

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

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


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM