完善资料让更多小伙伴认识你,还能领取20积分哦, 立即完善>
|
|
相关推荐
1个回答
|
|
1 激光雷达工作原理
大多数激光雷达采用光学三角测距威廉希尔官方网站 ,配合精密光学视觉采集处理机构,进行高频测距,每次测量过程中,激光雷达发射经过调制的红外激光信号,该激光信号经目标物体漫反射后被激光雷达的光学视觉采集系统接收,再由激光雷达内部处理器实时数据分析,计算出目标物体到雷达的距离以及当前的夹角,最后通过通讯接口输出到外部设备。 雷达是旋转测量一周,扫描得到周围一圈均匀分布点的信息(点的角度和距离)。SDK就是接收解析数据,得到每一圈点的信息。一圈360°被平均分为16帧上报扫描信息帧,所以得到16 帧的每帧起始角度分别是0°、22.5°、45°、67.5°、90°…270°、292.5°、315、337.5°、360°。16 帧数据加起来是完整一圈,一圈的总点数=16*每帧的点数;每帧的总点数根据扫描信息帧计算距离个数可以得到(距离个数=总点数)。每帧数据点的信息(角度和距离):一帧中第N 个点的距离是扫描信息帧中N 距离值,那一帧中第N 个点距离对应的角度=此帧起始角度+(N-1)*22.5/(每帧的总点数),这样就得到一帧点的角度和距离。 2 激光雷达通讯 实验使用的激光雷达的接口以及通讯方式如下,采用TTL串口通讯方式将数据输出到外部设备中去。 通讯帧结构 通讯帧由帧头、帧长度、协议类型、命令字、参数长度、参数、校验码组成, 主要用于外部设备和激光雷达之间的通讯,测量信息和故障信息的上传。 帧头: 固定为0xAA; 帧长度:是通讯帧的长度,帧长度计算是从帧头开始,到校验位前一字节(16 位无符号数, 低位在前,高位在后); 协议版本: 当前协议版本号(8 位无符号数); 命令字:命令字占1 Byte; Bit7: 通讯错误标志; Bit6: 通讯方向标志:0:主机---> 雷达; 1: 雷达---> 主机; Bit0 ~ Bit5: 是命令标识符; 参数长度:通讯帧中参数的长度(16 位无符号数, 低位在前,高位在后); 参数:命令的有效数据; 校验位:是从帧头开始到校验位前一字节的异或。(16 位无符号数,低位前,高位在后); 举例: AA 0A 00 04 56 03 00 01 CC 03 E1 01 AA:帧头标识。 0A 00:帧长度为0x000A(即10)字节(不包含校验位) 04:协议版本 56:通讯方向(0x40)+命令字(0x16) 03 00:有效数据长度0x0003 01:故障代码失速异常 CC 03:雷达转速0x03CC(972),即972*0.01(分辨率) = 9.72r/s E1 01:校验码为0x01E1=(AA+0A+…+CC+03) 3 MDK程序开发 制作了一个demo程序,使用USART1和激光雷达进行数据通讯,使用USART2作为打印串口,扫描一圈有512个数据点,打印第20到第50个数据点的角度和距离。 3.1 main.c编写 int main(void) { uint16_t i=0; uint16_t N=20; NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); USART1_Init(230400); USART2_Init(115200); Lidarscaninfo_Init(); SetLidarWorkMode(_8K_SCAN_MODE); printf("one circle point num:%dn",lidarscaninfo.OneCriclePointNum); printf("one circle point num:%dn",lidarscaninfo.OneCriclePointNum); while(1) { ProcessUartRxData(); if(lidarscaninfo.Result == LIDAR_GRAB_SUCESS) { lidarscaninfo.Result=LIDAR_GRAB_ING; printf("Point: ttt Anglettt Distancettn"); for(N=20;N<51;N++) { printf("%dttt %5.2fttt %5.2fttn", N, lidarscaninfo.OneCriclePoint[N].Angle, lidarscaninfo.OneCriclePoint[N].Distance); if(N==50) { printf("Point: ttt Anglettt Distancettn"); N=20; ProcessUartRxData(); } } } } } /*设置雷达工作模式*/ void SetLidarWorkMode(uint8_t workmode) { uint8_t i=0; uint16_t Len=0; T_PROTOCOL Preq; Preq.Header=FRAME_HEAD; Preq.Len=7+1; Preq.ProtoVer=PROTO_VER; Preq.CmdId=PC_TO_LD|CMD_SET_WORK_MODE; Preq.ParamLen=1; Len = Preq.Len+2; Big2LittleEndian_u16(Preq.Len); Big2LittleEndian_u16(Preq.ParamLen); memcpy(TxBuffer.Buff,&Preq,7); TxBuffer.Buff[7]=workmode; Preq.CheckSum=Calc_Pack_Checksum(TxBuffer.Buff,&TxBuffer.Buff[7],Len); TxBuffer.Buff[8]=Preq.CheckSum&0xFF; TxBuffer.Buff[9]=Preq.CheckSum>>8; for(i=0;i USART_SendData(USART1,TxBuffer.Buff); while (USART_GetFlagStatus(USART1, USART_FLAG_TXE) == RESET); //µÈ´ý·¢ËÍÍê } } 3.2 USART配置 /*初始化数据传送串口1*/ void USART1_Init(int baud) { GPIO_InitTypeDef GPIO_InitStructure; USART_InitTypeDef USART_InitStructure; NVIC_InitTypeDef NVIC_InitStructure; RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1|RCC_APB2Periph_GPIOA, ENABLE); GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(GPIOA,&GPIO_InitStructure); GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING; GPIO_Init(GPIOA,&GPIO_InitStructure); USART_DeInit(USART1); USART_InitStructure.USART_BaudRate = baud; USART_InitStructure.USART_WordLength = USART_WordLength_8b; USART_InitStructure.USART_StopBits = USART_StopBits_1; USART_InitStructure.USART_Parity = USART_Parity_No; USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None; USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx; USART_Init(USART1, &USART_InitStructure); USART_ITConfig(USART1, USART_IT_RXNE, ENABLE); USART_ITConfig(USART1, USART_IT_IDLE, ENABLE); USART_Cmd(USART1, ENABLE); USART_ClearITPendingBit(USART1, USART_IT_RXNE); USART_ClearITPendingBit(USART1, USART_IT_IDLE); NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn; NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=0x00 ; NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0x02; NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; NVIC_Init(&NVIC_InitStructure); } void USART1_IRQHandler(void) { volatile u8 Temp; if(USART_GetFlagStatus(USART1,USART_FLAG_RXNE) != RESET) { UartReceive(USART1->DR); USART_ClearFlag(USART1,USART_FLAG_RXNE); } if(USART_GetFlagStatus(USART1,USART_FLAG_IDLE) != RESET) { RxDataComplete(); USART_ClearFlag(USART1,USART_FLAG_IDLE); } Temp = USART1->SR; Temp = USART1->DR; } void RxDataComplete(void) { if((RxBuffer.Rdy == 0)&&(RxBuffer.Len > 0)) { if(RxBuffer.Len > 3) RxBuffer.Rdy = 1; else RxBuffer.Len = 0; } } void UartReceive(u8 data) { if(RxBuffer.Rdy == 0) { RxBuffer.Buff[RxBuffer.Len++] = data; if(RxBuffer.Len >= sizeof(RxBuffer.Buff)) RxBuffer.Rdy = 1; } } /*初始化打印串口2*/ void USART2_Init( int baud2) { GPIO_InitTypeDef GPIO_InitStructure; USART_InitTypeDef USART_InitStructure; NVIC_InitTypeDef NVIC_InitStructure; RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART2,ENABLE); RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE); GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(GPIOA,&GPIO_InitStructure); GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING; GPIO_Init(GPIOA,&GPIO_InitStructure); USART_DeInit(USART2); NVIC_InitStructure.NVIC_IRQChannel = USART2_IRQn; NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=0x00 ; NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0x01; NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; NVIC_Init(&NVIC_InitStructure); //³õʼ»¯NVIC¼Ä´æÆ÷ USART_InitStructure.USART_BaudRate = baud2; USART_InitStructure.USART_WordLength = USART_WordLength_8b; USART_InitStructure.USART_StopBits = USART_StopBits_1; USART_InitStructure.USART_Parity = USART_Parity_No; USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None; USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx; USART_Init(USART2, &USART_InitStructure); USART_ITConfig(USART2, USART_IT_RXNE, ENABLE); USART_ITConfig(USART2, USART_IT_IDLE, ENABLE); USART_Cmd(USART2, ENABLE); USART_ClearITPendingBit(USART2, USART_IT_RXNE); USART_ClearITPendingBit(USART2, USART_IT_IDLE); } int fputc(int ch, FILE *f) { USART_SendData(USART2, (uint8_t) ch); while (USART_GetFlagStatus(USART2, USART_FLAG_TXE) == RESET); return (ch); } 4实验结果分析 由于拿着激光雷达不停晃动,打印出的数据有些混乱,甚至有部分错误,暂时就不去处理了,读者理解即可,这里也只是演示一下就行了。 (谢谢大家,欢迎关注指正) |
|
|
|
只有小组成员才能发言,加入小组>>
调试STM32H750的FMC总线读写PSRAM遇到的问题求解?
1916 浏览 1 评论
X-NUCLEO-IHM08M1板文档中输出电流为15Arms,15Arms是怎么得出来的呢?
1680 浏览 1 评论
1172 浏览 2 评论
STM32F030F4 HSI时钟温度测试过不去是怎么回事?
771 浏览 2 评论
ST25R3916能否对ISO15693的标签芯片进行分区域写密码?
1732 浏览 2 评论
1973浏览 9评论
STM32仿真器是选择ST-LINK还是选择J-LINK?各有什么优势啊?
808浏览 4评论
stm32f4下spi+dma读取数据不对是什么原因导致的?
257浏览 3评论
STM32F0_TIM2输出pwm2后OLED变暗或者系统重启是怎么回事?
625浏览 3评论
634浏览 3评论
小黑屋| 手机版| Archiver| 电子发烧友 ( 湘ICP备2023018690号 )
GMT+8, 2025-1-24 21:18 , Processed in 0.734893 second(s), Total 75, Slave 59 queries .
Powered by 电子发烧友网
© 2015 bbs.elecfans.com
关注我们的微信
下载发烧友APP
电子发烧友观察
版权所有 © 湖南华秋数字科技有限公司
电子发烧友 (电路图) 湘公网安备 43011202000918 号 电信与信息服务业务经营许可证:合字B2-20210191 工商网监 湘ICP备2023018690号