興趣之余,利用晚上的時間,做一些個人興趣方面的開發. 之前沒接觸過 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