arduino 串口实时绘图

发布于 2021-2-3 09:32
浏览
0收藏

兴趣之余,利用晚上的时间,做一些个人兴趣方面的开发. 之前没接触过 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位数据分别发送,最后以换行符结尾.

"""
ldr.py
http://electronut.in/plotting-real-time-data-from-arduino-using-python/
Display analog data from Arduino using Python (matplotlib)

Author: Mahesh Venkitachalam
Website: electronut.in
"""
import ctypes
import sys, serial, argparse
import numpy as np
from time import sleep
from collections import deque

import matplotlib.pyplot as plt
import matplotlib.animation as animation


# plot class
class AnalogPlot:
  # constr
  def __init__(self, strPort, maxLen):
      # open serial port
      self.ser = serial.Serial(strPort, 38400)

      self.ax = deque([0.0]*maxLen)
      self.ay = deque([0.0]*maxLen)
      self.az = deque([0.0]*maxLen)
      self.gx = deque([0.0]*maxLen)
      self.gy = deque([0.0]*maxLen)
      self.gz = deque([0.0]*maxLen)
      self.mx = deque([0.0]*maxLen)
      self.my = deque([0.0]*maxLen)
      self.mz = deque([0.0]*maxLen)
      self.maxLen = maxLen

  # add to buffer
  def addToBuf(self, buf, val):
      if len(buf) < self.maxLen:
          buf.append(val)
      else:
          buf.pop()
          buf.appendleft(val)

  # add data
  def add(self, data):
      assert(len(data) == 9)
      self.addToBuf(self.ax, data[0])
      self.addToBuf(self.ay, data[1])
      self.addToBuf(self.az, data[2])
      self.addToBuf(self.gx, data[3])
      self.addToBuf(self.gy, data[4])
      self.addToBuf(self.gz, data[5])
      self.addToBuf(self.mx, data[6])
      self.addToBuf(self.my, data[7])
      self.addToBuf(self.mz, data[8])
  # update plot
  def update(self,frameNum,a0,a1,a2,a3,a4,a5,a6,a7,a8):
      try:
          data = self.ser.readline()
          length = len(data)
          if length == 24 and ord(data[0])== 83:
            count = (ord(data[1])<<8)+ord(data[2])
            value = (ord(data[3])<<8)+ord(data[4])
            ax = ctypes.c_int16(value).value
            value = (ord(data[5])<<8)+ord(data[6])
            ay = ctypes.c_int16(value).value
            value = (ord(data[7])<<8)+ord(data[8])
            az = ctypes.c_int16(value).value
            value = (ord(data[9])<<8)+ord(data[10])
            gx = ctypes.c_int16(value).value
            value = (ord(data[11])<<8)+ord(data[12])
            gy = ctypes.c_int16(value).value
            value = (ord(data[13])<<8)+ord(data[14])
            gz = ctypes.c_int16(value).value
            value = (ord(data[15])<<8)+ord(data[16])
            mx = ctypes.c_int16(value).value
            value = (ord(data[17])<<8)+ord(data[18])
            my = ctypes.c_int16(value).value
            value = (ord(data[19])<<8)+ord(data[20])
            mz = ctypes.c_int16(value).value

            array = [ax,ay,az,gx,gy,gz,mx,my,mz]
            print array
            self.add(array)
            a0.set_data(range(self.maxLen), self.ax)
            a1.set_data(range(self.maxLen), self.ay)
            a2.set_data(range(self.maxLen), self.az)
            a3.set_data(range(self.maxLen), self.gx)
            a4.set_data(range(self.maxLen), self.gy)
            a5.set_data(range(self.maxLen), self.gz)
            a6.set_data(range(self.maxLen), self.mx)
            a7.set_data(range(self.maxLen), self.my)
            a8.set_data(range(self.maxLen), self.mz)
      except KeyboardInterrupt:
          print('exiting')

      return a0,

  # clean up
  def close(self):
      # close serial
      self.ser.flush()
      self.ser.close()

# main() function
def main():
  # create parser
  #parser = argparse.ArgumentParser(description="LDR serial")
  # add expected arguments
  #parser.add_argument('--port', dest='port', required=True)

  # parse args
  #args = parser.parse_args()

  strPort = 'COM3'
  #strPort = args.port

  print('reading from serial port %s...' % strPort)

  # plot parameters
  analogPlot = AnalogPlot(strPort, 100)

  print('plotting data...')

  # set up animation
  fig = plt.figure()
  ax = plt.axes(xlim=(0, 100), ylim=(-20000, 20000))
  a0, = ax.plot([], [])
  a1, = ax.plot([], [])
  a2, = ax.plot([], [])
  a3, = ax.plot([], [])
  a4, = ax.plot([], [])
  a5, = ax.plot([], [])
  a6, = ax.plot([], [])
  a7, = ax.plot([], [])
  a8, = ax.plot([], [])
  anim = animation.FuncAnimation(fig, analogPlot.update,
                                 fargs=(a0,a1,a2,a3,a4,a5,a6,a7,a8),
                                 interval=50)

  # show plot
  plt.show()

  # clean up
  analogPlot.close()

  print('exiting.')


# call main
if __name__ == '__main__':
  main()

运行结果如下图:arduino 串口实时绘图-开源基础软件社区

 从互联网搜索了一下,可以串口绘图的工具很多,试了一下 SerialChart工具,感觉还不错,界面如下:arduino 串口实时绘图-开源基础软件社区

下位机数据格式较简单:

 

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

已于2021-2-3 09:32:55修改
收藏
回复
举报
回复
添加资源
添加资源将有机会获得更多曝光,你也可以直接关联已上传资源 去关联
    相关推荐