当前位置: 能电机 >> 能电机前景 >> 帅小伙自制手持建图仪基于STM32F1
引子
一个友人在做效劳机械人项目,用到思岚的激光雷达,因而便把淘汰的A1M8雷达送我一个,本着拿到啥就玩啥的立场,必然整一波。原来激光雷达如故搭配ROS才略表现最大的影响,怎么资本有限,气力不够,只可仰仗STM32开采板做一个及其粗陋的舆图扫描。
思岚A1M8激光雷达
这款激光雷达属于低成本的度激光扫描测距雷达,外置机电,利用皮带动员雷达转台转化,实行度的测距扫描,机电的转速由MCU发送PWM管制。
外部系统经过TTL电平的UART串口记号与RPLIDAR测距重心举行通信。经过本文档界说的通信协定,外部系统也许及时获得RPLIDAR的扫描数据、设施音信、设施矫健形态。而且经过联系夂箢调换RPLIDAR的处事形式。
遵从不同的恳求范例,RPLIDAR具备三种不同的恳求/应答形式:
准则的单次恳求-单次应答形式
单次恳求-屡次应答形式
单次恳求/无应答形式
关于中止扫描、重启测距重心这种恳求夂箢,RPLIDAR采取单次恳求,但不做应答的通信形式。此时外部系统需求在发送恳求后等候必然的光阴,待RPLIDAR实行了上一次恳求职掌后方可赓续履行下一次恳求。不然第二次的恳求将或者被RPLIDAR丢弃。
在这次运用中,紧要采取后两种恳求/应答形式,利用单次恳求-屡次应答形式搜聚测距数据,利用单次恳求/无应答形式中止采样,举行数据的处置。
在单次恳求-屡次应答形式搜聚测距数据时,MCU发送搜聚指令,雷达会先答复一条起使应答报文,今后便会轮回答复数据应答报文。
恳求报文及肇始应答数据格式以下:
在答复肇始应答今后,雷达会轮回答复测距数据。长度为5bytes。
譬喻测距数据为3ED。
第一个字节:3E,二进制为:。代表记号品质为0x0f。记号品质不为零代表数据灵验,肇始标识位为0,代表不是新的一圈,该标识位惟独在新的一圈的第一帧数据才会置一,该圈内的其尾数据改成如故是0。
第二个字节:D5,角度数据低七位。
第三个字节:16,角度数据高八位,加之第二个字节的低七位即是A,再右移一位得B35。理论角度=/64=44°,该角度示意与雷达零度的顺时针偏移角度,以下图。
第四个字节:77,间隔数据低八位。
第五个字节:06,间隔角度高八位。则此时间隔为0x/4=mm。
激光雷达测试:
接线:
雷达MCU
GND-----------GND
RX-------------TX
TX-------------RX
V5.0-----------5V
GND-----------GND
MOTOCTL----PWM
VMOTO-------5V
首先测试利用串口副手举行数据搜聚,这边将MOTOCTL接到5V电源,直接以最高速率举行采样。串口副手发送A,也许看到数据震动。
个中初阶的七位数据对应肇始应答,背面每5个字节一组,对应测距数据。雷达无毁坏,开端毗邻开采板调试。
MCU代码:
既然是USART通信,咱们先初始化USART,利用串口接管间断接管数据。
voidUSART_Config(void){GPIO_InitTypeDefGPIO_InitStructure;USART_InitTypeDefUSART_InitStructure;NVIC_InitTypeDefNVIC_InitStructure;//翻开串口GPIO的时钟DEBUG_USART_GPIO_APBxClkCmd(DEBUG_USART_GPIO_CLK,ENABLE);//翻开串口外设的时钟DEBUG_USART_APBxClkCmd(DEBUG_USART_CLK,ENABLE);//将USARTTx的GPIO建设为推挽复用形式GPIO_InitStructure.GPIO_Pin=DEBUG_USART_TX_GPIO_PIN;GPIO_InitStructure.GPIO_Mode=GPIO_Mode_AF_PP;GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;GPIO_Init(DEBUG_USART_TX_GPIO_PORT,GPIO_InitStructure);//将USARTRx的GPIO建设为浮空输入形式GPIO_InitStructure.GPIO_Pin=DEBUG_USART_RX_GPIO_PIN;GPIO_InitStructure.GPIO_Mode=GPIO_Mode_IN_FLOATING;GPIO_Init(DEBUG_USART_RX_GPIO_PORT,GPIO_InitStructure);//Usart1NVIC建设NVIC_InitStructure.NVIC_IRQChannel=USART1_IRQn;NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=2;//抢占优先级3NVIC_InitStructure.NVIC_IRQChannelSubPriority=3;//子优先级3NVIC_InitStructure.NVIC_IRQChannelCmd=ENABLE;//IRQ通道使能NVIC_Init(NVIC_InitStructure);//依据指定的参数初始化VIC存放器//建设串口的处事参数//建设波特率USART_InitStructure.USART_BaudRate=DEBUG_USART_BAUDRATE;//建设针数据字长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(DEBUG_USARTx,USART_InitStructure);USART_ITConfig(USART1,USART_IT_RXNE,ENABLE);//开启接管间断USART_ClearFlag(USART1,USART_FLAG_TC
USART_FLAG_RXNE);//USART_DMACmd(USART1,USART_DMAReq_Rx,ENABLE);//开启串口DMA接管//使能串口USART_Cmd(DEBUG_USARTx,ENABLE);}
而后编写间断效劳函数:
voidUSART1_IRQHandler(void)//串口1间断效劳程序{if(USART_GetITStatus(DEBUG_USARTx,USART_IT_RXNE)!=RESET){rxbuff[Res]=USART_ReceiveData(DEBUG_USARTx);Res++;if(Res==){USART_ITConfig(USART1,USART_IT_RXNE,DISABLE);//开启接管间断USART_SendData(USART1,0xA5);while(USART_GetFlagStatus(DEBUG_USARTx,USART_FLAG_TXE)==RESET);USART_SendData(USART1,0x25);while(USART_GetFlagStatus(DEBUG_USARTx,USART_FLAG_TXE)==RESET);Data_Processing();Res=0;ClearFlag=1;}//MYDMA_Enable(DMA1_Channel5);//开端一次DMA传输!}}
在串口间断效劳函数中,需求搜聚个数据(个测距点*5字节+肇始7个字节)。我采取全速采样,即MOTOCTL直接接5V,这边搜聚个数据点原来不只一圈的数据,不过由于每个度都有失效数据,多搜聚点也许使后期画图更完好。在索取数据利用EXCEL解析今后,全速转一圈大概采样个点左右,这个数据无奈牢固,每一圈采样数均不同样。
在搜聚数据实行后咱们需求关上采样,由于STM32F的数据处置才能并不睬想,这边需求必然的光阴,因而经过串口发送指令A让雷达中止采样,同时移用函数Data_Processing();举行数据处置以及在屏幕上画点。这边要留心,雷达在中止采样前会将着末一帧数据发送完好,咱们在发送中止指令的期间,雷达或者曾经在筹办下一帧数据,在发送完中止指令今后,或者会存在这一帧数据的着末一位未触发间断,不过串口的数据存放器中曾经保管了这位数据,且曾经改动了标识位,是以鄙人一次启动采样时会致使收到的第一个数据是上一次未接管完的数据。这个在举行处置。
在此以前咱们还需求一个触发采样的按键。按下按键后触发采样,为了维持连续采样,在串口接管间断关上采样并处置完数据后,可在主轮回中再次开启。
voidKEY1_IRQHandler(void){u8RX;//保证能否形成了EXTILine间断if(EXTI_GetITStatus(KEY1_INT_EXTI_LINE)!=RESET){USART_SendData(USART1,0xA5);while(USART_GetFlagStatus(DEBUG_USARTx,USART_FLAG_TXE)==RESET);USART_SendData(USART1,0x20);while(USART_GetFlagStatus(DEBUG_USARTx,USART_FLAG_TXE)==RESET);USART_ITConfig(USART1,USART_IT_RXNE,ENABLE);//开启悠闲间断Res=0;//肃清间断标识位EXTI_ClearITPendingBit(KEY1_INT_EXTI_LINE);}}
数据处置以下:
voidData_Processing(void){u16i,j=7;u8quality;for(i=0;i;i++){quality=rxbuff[j]2;if(quality!=0){data_rage1=rxbuff[j+2]8;data_rage2=rxbuff[j+1];angle[i]=(data_rage1
data_rage2)1;angle[i]=angle[i];data_rage1=rxbuff[j+4]8;data_rage2=rxbuff[j+3];distance[i]=(data_rage1
data_rage2);//Usart_SendHalfWord(USART2,angle[i]);//Usart_SendHalfWord(USART2,distance[i]);}j=j+5;}if(i==){LCD_Draw();i=0;//}}
从串口缓存数组中掏出角度值和间隔值,保管在数组angle[]和distance[]中。当个数据点处置完,移用画图函数举行屏幕绘制。
voidLCD_Draw(void){u16i;ILI_Clear(0,0,LCD_X_LENGTH,LCD_Y_LENGTH);/*清屏,显示全黑*/LCD_SetTextColor(RED);for(i=0;i;i++){x=return_x(angle[i],distance[i]/scale);y=return_y(angle[i],distance[i]/scale);//ILI_DrawLine(,,x,y);ILI_SetPointPixel(x,y);/*为了点更理解,在点范畴画扶助点*/ILI_SetPointPixel(x+1,y+1);ILI_SetPointPixel(x-1,y-1);ILI_SetPointPixel(x-1,y+1);ILI_SetPointPixel(x+1,y-1);ILI_SetPointPixel(x+2,y+2);ILI_SetPointPixel(x-2,y-2);ILI_SetPointPixel(x-2,y+2);ILI_SetPointPixel(x+2,y-2);}}
画点直接移用野火的库,个中参数scale为舆图夸大倍数,由于屏幕巨细有限,为了适应不同巨细的舆图,利用该参数举行舆图夸大。
return_x,return_y函数是将测距点调动为屏幕坐标。原函数以下:
//x坐标调动函数//ang:0~度数,d:间隔//返回:x坐标0~floatreturn_x(u16ang,signedintd){floatx;doubleang_deg,dd;ang_deg=ang/64;dd=d/4;if(dd!=0){if(ang_deg=90){x=dd*sin(ang_deg)+;//角度调动成弧度}elseif((ang_deg90)(ang_deg=)){x=+dd*sin(ang_deg);}elseif((ang_deg)(ang_deg=)){x=-dd*sin(ang_deg);}elseif((ang_deg)(ang_deg=)){x=-dd*sin(ang_deg);}}if(x)x=;if(x0)x=0;returnx;}//y坐标调动函数//ang:0~度数,d:间隔//返回:y坐标0~floatreturn_y(u16ang,signedintd){floaty,dd;doubleang_deg;ang_deg=ang/64;dd=d/4;if(dd!=0){if(ang_deg=90){y=-dd*cos(ang_deg);//角度调动成弧度}elseif((ang_deg90)(ang_deg=)){y=dd*cos(ang_deg)+;}elseif((ang_deg)(ang_deg=)){y=dd*cos(ang_deg)+;}elseif((ang_deg)(ang_deg=)){y=-dd*cos(ang_deg);}}if(y)y=;if(y0)y=0;returny;}
此时在屏幕上就可绘制出雷达采样点
这边是动态监测的,不过动态图在背面补,后续也会优化画图和数据处置,这边先给出大概的功效。光阴有限,现在先如此,背面会完满此贴。
从正文也许看出该屏幕的显示的扫描舆图是圆形,不过我的房间却不是圆的。这个舆图显然是有题目。不过不论无何如调换算法,显示到屏幕上的测距点老是不切确。解析得出大概题目是出在屏幕上,由于屏幕分辩率有限,测的的尺寸为了能在屏幕上显示,不得已将尺寸减少几十倍,致使数据严峻失真。因而我将测距数据导出协商。这次用已知巨细的物料箱将雷达倒扣在内里。物料箱的尺寸大概为36cm*45cm。手头没有卷尺,用一个小尺子量的,是以不过大概值。
雷达位于箱子中心,那末到最短到箱壁双方的间隔大概是18和22.5厘米。
测试开端:
利用串口二将原始角度和间隔值打印到串口副手:
利用world文档将数据整顿:
而后复制数据到excle,举行数据处置,将角度和间隔别离索取;
依据的确角度值采用一整圈间隔数据(mm),插入雷达图:
此图由于有失效点,掏出零点以及差错点后获得以下图。
也许看到此时的雷达图很逼近咱们的箱子的确形态,间隔巨细也切合箱子尺寸。此时才也许做为胜利,固然屏幕任然无奈完好显示扫描舆图,不过数据的处置并无题目,单片机速率跟不上,屏幕分辩率也不够,痛苦啊。
思岚A1M8测试.rar(4.76MB,下载
转载请注明:http://www.aideyishus.com/lkcf/1302.html