• 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] = '
    ';
      tmpData[dataLens - 1] = '
    ';
    
      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

  • 相关阅读:
    第十五讲 实例模式
    第十四讲 实例模式
    将博客搬至CSDN
    CSU 1616: Heaps(区间DP)
    hdu 1281棋盘游戏(二分匹配)
    hdu 1042 N!(大数的阶乘)
    hdu 3371 Connect the Cities (最小生成树Prim)
    hdu 4502吉哥系列故事——临时工计划 (简单DP)
    hdu1230火星A+B (大数题)
    hdu1301 Jungle Roads (Prim)
  • 原文地址:https://www.cnblogs.com/dreamfactory/p/5375697.html
Copyright © 2020-2023  润新知