最近在用JY901做一些实验,关于JY901网上有很多资料了,也有上位机软件,可以方便的查看输出数据。我想做的是对输出的角速度进行积分,对比积分后的结果与输出的角度,如果数据都比较准确地话,那么他们应该相差不大。

这篇文章里,要完成的事情就是通过串口接收他输出的角速度和角度,然后对角速度进行积分,并实时显示数据结果。下面我首先对各个部分进行分块解释,完整的代码放在最后。

1. 串口通信

python实现串口通信可以用 pySerial 库。我们首先选择串口对应的设备端口:

# 获取串口设备对应的端口
def get_serial_port():ports = list(serial.tools.list_ports.comports())for port in ports:print(ports.index(port), port)selected = -1while selected < 0 or selected >= len(ports):print("please input serial to use [start from 0]:")selected = int(input())print("selected: ", selected)port = ports[selected]print("use ", port)port = list(port)return port[0]

然后打开串口并持续接收数据,在收到的数据中提取IMU数据:

def serial_readers(self, port = None, size = 22):# port   : 串口端口# size   : 默认一次读取数据长度(bytes)if not port:port = get_serial_port()total = bytearray()ser = Nonewhile True:try:if not ser:ser = serial.Serial(port, 115200, timeout=60)if not ser.is_open:ser.open()tmp = ser.read(size)total.extend(tmp)total, ext_omega, ext_angle = self.extract_raw_data(total)   #提取IMU数据except Exception as e:print("exception ", e)if ser:ser.close()time.sleep(5)return self.record_omega, self.record_angle

2. IMU数据提取

首先我们来看JY901串口数据的帧结构:

加速度:0x55 0x51 AxL AxH AyL AyH AzL AzH TL TH SUM
角速度:0x55 0x52 wxL wxH wyL wyH wzL wzH TL TH SUM
角度:  0x55 0x53 RollL RollH PitchL PitchH YawL YawH TL TH SUM

这三种数据帧长度都是 11 Bytes,最后一位为校验位,我们从串口数据中提取IMU数据也是根据这个帧结构,先检测帧头,然后读取整个帧(代码里偷了懒,并没有核对校验位)

def extract_raw_data(self, data):# 根据报文格式读取角速度数据# 0x55 0x52 + data + CRC(8bits)length = 9ext_omega = Noneext_angle = Nonetry:st = data.index(b'\x55')                # 寻找报文引导字if st >= 0:reserved = data[st+1]               # 数据类型if reserved == 82:                  # 0x52,提取角速度消息if st+length+1 < len(data):if self.count_omega==0:self.time_now = self.time_last = time.time()else:self.time_last = self.time_nowself.time_now = time.time()ext_omega = data[st:st+length+2]temp = int.from_bytes(ext_omega[6:8], byteorder='little', signed=True)self.omega = temp/32768*2000self.record_omega.append(self.omega)   #deg/sdata = data[st+length+2:]self.count_omega += 1self.omega_inte += self.omega*(self.time_now - self.time_last)self.omega_inte = (self.omega_inte+180)%360 - 180self.record_inte.append(self.omega_inte)elif reserved == 83:                # 0x53,提取角度消息if st+length+1 < len(data):ext_angle = data[st:st+length+2]temp = int.from_bytes(ext_angle[6:8], byteorder='little', signed=True)self.yaw = temp/32768*180if self.count_yaw==0:                   #记录初始相位self.yaw_init = self.yawself.record_angle.append(self.yaw - self.yaw_init)      #degdata = data[st+length+2:]self.count_yaw += 1elif reserved == 81:                # 0x51, 丢弃加速度消息if st+length+1 < len(data):ext_data = Nonedata = data[st+length+2:]else:data = data[st+2:]except:return data, ext_omega, ext_angleif self.count_yaw%100 == 0 and self.count_yaw>0:self.save_data()print(len(self.record_omega),' extract omega  ',ext_omega,self.omega_inte)print(len(self.record_angle),' extract angle  ',ext_angle,self.yaw - self.yaw_init)print('*'*30)return data, ext_omega, ext_angle

3. 绘图显示

我把历史接收数据都存在一个 list 里面了,每过 0.1s 就重新绘图,看起来就像是在实时更新一样。

def plot(self):plt.ion()plt.figure()while True:try:if len(self.record_angle)>0 and len(self.record_inte)>0 :plt.clf()plt.plot(list(range(len(self.record_angle))),self.record_angle,'r')plt.plot(list(range(len(self.record_inte))),self.record_inte,'b')plt.xlim(max(0,self.count_yaw-3000),self.count_yaw+200)plt.legend(labels=['angle','integration'])plt.pause(0.1)plt.ioff()except Exception as e:print("exception ", e)

4. 运行效果

当时忘记保存截图了,这里就不放了 emmmm

5. 完整代码

为了便于共享数据,定义了一个类 JY901,将上面的各个函数放在这个类里面,输出的数据也都记录在 JY901 的成员变量里。

import serial
import serial.tools.list_ports
import time
import struct
import matplotlib.pyplot as plt
import numpy as np
import threadingclass JY901():def __init__(self):self.time_last = 0self.time_now = 0self.record_angle = []self.record_omega = []self.record_inte = []self.count_yaw = 0self.count_omega = 0self.omega_inte = 0         #角速度积分self.yaw_init = 0self.yaw = 0self.omega = 0def extract_raw_data(self, data):# 根据报文格式读取角速度数据# 0x55 0x52 + data + CRC(8bits)length = 9ext_omega = Noneext_angle = Nonetry:st = data.index(b'\x55')                # 寻找报文引导字if st >= 0:reserved = data[st+1]               # 数据类型if reserved == 82:                  # 0x52,提取角速度消息if st+length+1 < len(data):if self.count_omega==0:self.time_now = self.time_last = time.time()else:self.time_last = self.time_nowself.time_now = time.time()ext_omega = data[st:st+length+2]temp = int.from_bytes(ext_omega[6:8], byteorder='little', signed=True)self.omega = temp/32768*2000self.record_omega.append(self.omega)   #deg/sdata = data[st+length+2:]self.count_omega += 1self.omega_inte += self.omega*(self.time_now - self.time_last)self.omega_inte = (self.omega_inte+180)%360 - 180self.record_inte.append(self.omega_inte)elif reserved == 83:                # 0x53,提取角度消息if st+length+1 < len(data):ext_angle = data[st:st+length+2]temp = int.from_bytes(ext_angle[6:8], byteorder='little', signed=True)self.yaw = temp/32768*180if self.count_yaw==0:                   #记录初始相位self.yaw_init = self.yawself.record_angle.append(self.yaw - self.yaw_init)      #degdata = data[st+length+2:]self.count_yaw += 1elif reserved == 81:                # 0x51, 丢弃加速度消息if st+length+1 < len(data):ext_data = Nonedata = data[st+length+2:]else:data = data[st+2:]except:return data, ext_omega, ext_angleif self.count_yaw%100 == 0 and self.count_yaw>0:self.save_data()print(len(self.record_omega),' extract omega  ',ext_omega,self.omega_inte)print(len(self.record_angle),' extract angle  ',ext_angle,self.yaw - self.yaw_init)print('*'*30)return data, ext_omega, ext_angledef serial_readers(self, port = None, size = 22):# port   : 串口端口# size   : 默认一次读取数据长度(bytes)if not port:port = get_serial_port()total = bytearray()ser = Nonewhile True:try:if not ser:ser = serial.Serial(port, 115200, timeout=60)if not ser.is_open:ser.open()tmp = ser.read(size)total.extend(tmp)total, ext_omega, ext_angle = self.extract_raw_data(total)except Exception as e:print("exception ", e)if ser:ser.close()time.sleep(5)return self.record_omega, self.record_angledef save_data(self):np.savez('record.npz',record_omega=self.record_omega, record_angle=self.record_angle)def plot(self):plt.ion()plt.figure()while True:try:if len(self.record_angle)>0 and len(self.record_inte)>0 :plt.clf()plt.plot(list(range(len(self.record_angle))),self.record_angle,'r')plt.plot(list(range(len(self.record_inte))),self.record_inte,'b')plt.xlim(max(0,self.count_yaw-3000),self.count_yaw+200)plt.legend(labels=['angle','integration'])plt.pause(0.1)plt.ioff()except Exception as e:print("exception ", e)def get_serial_port():ports = list(serial.tools.list_ports.comports())for port in ports:print(ports.index(port), port)selected = -1while selected < 0 or selected >= len(ports):print("please input serial to use [start from 0]:")selected = int(input())print("selected: ", selected)port = ports[selected]print("use ", port)port = list(port)return port[0]if __name__ == '__main__':imu = JY901()thread_rcv = threading.Thread(target=imu.serial_readers)thread_plt = threading.Thread(target=imu.plot)thread_plt.start()thread_rcv.start()

JY901串口数据接收与处理(Python)相关推荐

  1. 【Qt串口调试助手】1.2 - 串口数据接收不发生换行,CH340 / CP2102 多硬件兼容

    上一篇提到:对串口接收的显示,使用的是当前位置插入+移动鼠标光标到末尾的方式.这种方法可以有效解决 串口数据接收发生换行的问题,并且解决 CH340 / CP2102 多硬件显示结果不一致的问题.那有 ...

  2. HAL库教程6:串口数据接收

    STM32的串口接收机制   与阻塞式发送函数HAL_UART_Transmit配套,有个阻塞式的接收函数,HAL_UART_Receive,但此函数不常用,串口接收通常使用中断函数HAL_UART_ ...

  3. 串口数据实时处理:定时器+串口 判断串口数据接收完成

    使用背景: 之前在做项目的时候,串口接收的数据要及时进行处理,虽然采用了自定义的串口协议,但是协议的包尾只有一个字节,经常判断不准数据是否接受完毕,所以就采用计时器+串口的方式来判定串口是否接受完成. ...

  4. STM32G070RBT6基于Arduino框架下串口数据接收使用示例

    STM32G070RBT6基于Arduino框架下串口数据接收使用示例 相关篇<STM32G070RBT6基于Arduino串口的使用>

  5. python串口数据绘图_使用Python串口实时显示数据并绘图的例子

    使用pyserial进行串口传输 一.安装pyserial以及基本用法 在cmd下输入命令pip install pyserial 注:升级pip后会出现 "'E:\Anaconda3\Sc ...

  6. python读取串口数据 绘图_使用Python串口实时显示数据并绘图的例子

    使用pyserial进行串口传输 一.安装pyserial以及基本用法 在cmd下输入命令pip install pyserial 注:升级pip后会出现 "'E:Anaconda3Scri ...

  7. 万能的串口数据接收及处理方法

    搞单片机,肯定少不了串口的使用,不管是调试也好,与其他设备通信也好,是我们不可或缺的利器.接下来就分享一下本人在项目中使用串口接收数据及处理的方法. 先介绍下主要思路,首先需要开一个定时器,我们接收串 ...

  8. 关于串口数据接收出错问的问题(RS232、RS422、UART)

    这两天调试串口驱动,串口驱动应该是很简单的啊,但是发现数据接收的时候,总是偶尔会出现错误,经过不断的排查,终于找到了问题的关键所在. 一段串口的verilog代码如下: module uart_rx( ...

  9. STM32 —— 串口数据接收

    STM32 -- 串口接收数据 我们已经在前面的博客中讲过了串口通信中发送数据和中断的一些基本原理,这里主要介绍串口接收数据的相关内容 定长字符串的接收 当接收单字节时,我们就可以使用最简单的接收方式 ...

最新文章

  1. python模块之imghdr检测图片类型
  2. 反射获取构造方法并运行的快速的方式
  3. 服务器开机需要按f2才能进系统吗,win7系统电脑每次开机总要按F2才能进入系统怎么办...
  4. java linux 调用so文件,linux下java jni调用.so文件的方法
  5. mysql可视化创建外键说明_关于使用可视化图形工具navicat for mysql来创建外键的步骤...
  6. 开放大学毕业生自我鉴定计算机,开放大学毕业生自我鉴定范文500字(精选7篇)...
  7. cs1.6服务器修改游戏类型,如何自己架设CS1.6服务器?
  8. 台式计算机电源接线图,​台式机硬盘电源线接法【图解】
  9. 木秀于林,风必摧之;行高于人,众必毁之?
  10. 用计算机管理从新分区,电脑如何分区硬盘分区_电脑怎么重新分区教程-win7之家...
  11. 同步通信 VS 异步通信
  12. Matlab符号微积分练习
  13. 2021年熔化焊接与热切割复审考试及熔化焊接与热切割作业模拟考试
  14. 暴走欧洲之 为信仰买单
  15. 你真的了解服务器托管收费标准吗?
  16. Python练习题——统计字符串中分别有多少个字母数字空格及特殊字符
  17. mac日常使用小技巧
  18. OAuth 2.0 文档
  19. 什么是c 语言中源文件,C++中头文件和源文件详细介绍
  20. 你是如何理解 HTML 语义化的?

热门文章

  1. 1 - 概率论与数理统计
  2. 阿里云 MNS 切换为 自建 RabbitMQ
  3. 第52篇 QML自定义组件 — 组件化图片文字组合按钮
  4. 开篇之作之——阅读与思考
  5. Android studio 报错 :Unable to delete file
  6. pythonmath反三角函数的导数_Python求离散序列导数的示例
  7. MATLAB-直方图均衡化
  8. 曙光W580-G20来电自启
  9. 打开软件字体显示太小解决办法
  10. 【英雄哪里出来】一文带你吃透算法