兴趣之余,利用晚上的时间,做一些个人兴趣方面的开发. 之前没接触过 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 > 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.py3 http://electronut.in/plotting-real-time-data-from-arduino-using-python/
4 Display analog data from Arduino usingPython (matplotlib)5
6 Author: Mahesh Venkitachalam7 Website: electronut.in
8 """9 import ctypes10 import sys, serial, argparse11 import numpy asnp12 fromtime import sleep13 fromcollections import deque14
15 import matplotlib.pyplot asplt16 import matplotlib.animation asanimation17
18
19 # plot class
20 classAnalogPlot:21 # constr22 def __init__(self, strPort, maxLen):23 # open serial port24 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 =maxLen36
37 # add to buffer38 def addToBuf(self, buf, val):39 if len(buf) <40 buf.append else:42 buf.pop buf.appendleft>
45 # add data46 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 plot58 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).value66 value = (ord(data[5])<<8)+ord(data[6])67 ay =ctypes.c_int16(value).value68 value = (ord(data[7])<<8)+ord(data[8])69 az =ctypes.c_int16(value).value70 value = (ord(data[9])<<8)+ord(data[10])71 gx =ctypes.c_int16(value).value72 value = (ord(data[11])<<8)+ord(data[12])73 gy =ctypes.c_int16(value).value74 value = (ord(data[13])<<8)+ord(data[14])75 gz =ctypes.c_int16(value).value76 value = (ord(data[15])<<8)+ord(data[16])77 mx =ctypes.c_int16(value).value78 value = (ord(data[17])<<8)+ord(data[18])79 my =ctypes.c_int16(value).value80 value = (ord(data[19])<<8)+ord(data[20])81 mz =ctypes.c_int16(value).value82
83 array =[ax,ay,az,gx,gy,gz,mx,my,mz]84 print array85 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 returna0,99
100 # clean up101 def close(self):102 # close serial103 self.ser.flush()104 self.ser.close()105
106 # main() function107 def main():108 # create parser109 #parser = argparse.ArgumentParser(description="LDR serial")110 # add expected arguments111 #parser.add_argument('--port', dest='port', required=True)112
113 # parse args114 #args =parser.parse_args()115
116 strPort = 'COM3'
117 #strPort =args.port118
119 print('reading from serial port %s...' %strPort)120
121 # plot parameters122 analogPlot = AnalogPlot(strPort, 100)123
124 print('plotting data...')125
126 # setup animation127 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 plot143 plt.show()144
145 # clean up146 analogPlot.close()147
148 print('exiting.')149
150
151 # call main152 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
40>