python与串口通信

激光雷达通信协议解析

  • 串口基本属性:

    波特率:230400
    数据:8位数据,一位停止位,无校验位

  • 数据协议解析
  1. 单数据包结构及字节偏移:


    数据包如图所示,数据为小段存储。

  2. 距离信息解析

  • 每包数据的第8到55个字节是雷达测得的距离信息,每三个字节为一组,表示一个采样点的距离(第三个字节为强度信息,计算距离时不用)。
    距离信息的MSB的高两位为数据有效标志位,01为有效,10无效,可用以下方式判断:
    if SLx.MSB & 0xC0 == 64:#采样点有效
  • 距离的计算:
    SLx.Distance = ((SLx.MSB & 0x3F) << 8) | SLx.LSB 
  1. 角度信息解析
  • 每包数据的第6、7字节为起始角信息,第56/57字节为终止角信息。
  • 起始角和终止角的计算:
    firstangle = ((cache[5] << 8 | cache[4])-0xA000)/64 
    lastangle = ((cache[55] << 8 | cache[54])-0xA000)/64
  • 假设激光雷达的角速度是不变的,那么就可以得到16个采样点每个点的角度信息:
          if firstangle<lastangle:
              delta_angle=lastangle-firstangle
          else:
              delta_angle=360+lastangle-firstangle
          while j<16:
              self.A.append(firstangle+j*delta_angle/15)
              j+=1

    python与激光雷达串口通信

  • 设置串口波特率,调用串口函数进行初始化。
      from machine import Pin, UART
      def __init__(self,baudRate=115200,handler=None):
          self.port=UART(1, baudrate=baudRate, tx=17, rx=16)
  • 使用UART.read(1)函数从串口读取1字节数据,此时需注意判断所读取的数据是否为
    def Read(self,length=1024,strict=True):#数据读取,长度为length
      cache=[]
      if not strict:
        while self.port.any() and len(cache)<length:#缓存区数据和cache数据长度小于len
          cache.append(ord(self.port.read(1)))
      else:
        while len(cache)<length:
          tmp=self.port.read(1)
          if tmp!=None: 
            cache.append(ord(tmp))
      return cache
  • 从串口 逐个 读取1字节数据,来判断数据包头的位置(包头为0xaa55,小端存储),以便后续的信息提取。
      while(count<num):
              if(data_1[0]==0x55):
                  data_2=self.usart.Read(1)
                  if(data_2[0]==0xaa):
                      self.ori_data_get()
                      count+=1
                  else:
                      data_1=data_2
              else:
                  data_1=self.usart.Read(1)
  • 得到包头后,再读取一包数据的剩余的58个数据,并进行极坐标的计算。
    注意用
    if cache[7+3*i]&0xc0==64: 来判断该采样点的数据是否有效。如全部有效将会得到16个距离信息和16个角度信息。
      def ori_data_get(self):
          length=58
          cache=[]
          while len(cache)<length:
              tmp=self.usart.Read(1)
              cache.append(tmp[0])
          self.pole_data_cal(cache)#获取剩余的58个数据
      def pole_data_cal(self,cache):
          i=0
          firstangle = ((cache[5] << 8 | cache[4])-0xA000)/64 
          lastangle = ((cache[55] << 8 | cache[54])-0xA000)/64
          if firstangle<lastangle:
              delta_angle=lastangle-firstangle
          else:
              delta_angle=360+lastangle-firstangle#计算角度差
          while i<16:
              if cache[7+3*i]&0xc0==64:#判断该采样点的数据是否有效
                  dis=((cache[7+i*3]&0x3f)<<8)|cache[6+i*3]#计算有效点的距离
                  self.D.append(dis)
                  self.A.append(firstangle+i*delta_angle/15)
              i+=1
  • 将获得的极坐标数据转化为平面直角坐标数据。 注意角度和弧度的转换
      x=distance_num[i]*cos(angle_num[i]*3.1415926/180)
      y=distance_num[i]*sin(angle_num[i]*3.1415926/180)

    雷达的显示

  • st7753s屏幕的坐标范围为 128×160为了将雷达数据显示在屏幕上且以屏中心为原点,进行如下线性变换。

    x_new=int(round(xy1[0]/15))+64
    y_new=int(round(xy1[1]/15))+80

  • 雷达每次数据采集转过的角度约为 10° ,为了采集一周的数据,可将雷达采集次数设置为 36 ,即每采集36次清除屏幕数据一次。由于雷达会有无效数据点的存在,我们可以将采集次数设置为 72 以保证数据的完整性。
  • 完整的.py代码如下:
      def show_radar(self):#在屏幕上显示雷达数据
          while True:
              self.lcd.clear()#清屏
              for i in range(72):
                  xy=self.radar.xandy_data()#获取雷达数据
                  #self.lcd.clear()
                  for i in range(len(xy)):
                      xy1=xy[i]
                      x_new=int(round(xy1[0]/15))+64
                      y_new=int(round(xy1[1]/15))+80#将雷达数据线性变换到屏幕上的点
                      self.lcd.pixel(x_new,y_new,1)
                      self.lcd.show()#显示
作者:admin  创建时间:2024-03-20 15:22
最后编辑:rd.you  更新时间:2024-07-17 11:01