本帖最后由 我94喜欢丰兄 于 2024-9-20 14:52 编辑
本帖最后由 我94喜欢丰兄 于 2024-2-28 23:56 编辑
本帖最后由 我94喜欢丰兄 于 2024-2-28 15:35 编辑
前言
去年无意间在B站上看到有些大佬利用小米摄像头来结合流浪地球中的MOSS,让MOSS的可以实现视觉跟踪(实际就是小米摄像头的其中一个功能而已),但是跟随的不是很流畅,总体来说还是不错的。所以我就决定自己也做一个。在淘宝买材料的时候,发现安信可新款雷达模组Rd-03D已经上市,该雷达采用一发两收的天线,可以实现目标跟踪,实现对区域内目标测距、测角和测速。感觉这个还不错,就想买回来和摄像头结合一下。让MOSS拥有两个系统,一个是自身的系统,另一个就是以STM32为主控芯片的语音控制系统。
通过利用STM32解析Rd-03D的串口数据,当雷达功能开启的时候,检测人体距离雷达的角度,根据角度来调整X轴移动,实现摄像头跟随的效果。(Y轴的俯仰角的控制现在没有去设计考虑)还有就是关于两个系统之间的切换设计等还未完全搞定,都是边做边想。如果有小伙伴有啥好的建议可以一起评论区讨论。
一:Rd-03D引脚说明
J1引脚说明:
J2引脚说明:
二、硬件构成
RD-03D雷达+STM32最小系统板+ASR-PRO离线语音模块+ESP-12F+步进电机+自制整合电路板等模块
1、原理图
我想把它放在一张图上,看着有点乱。
2、印制电路板
3、实物图(不完全体)
三、软件编写
这里由于用到了ASR-PRO和STM32模块,需要分别利用KEIL和天问编程软件编写,在这里不做详细讲解,小伙伴可以自行下载资料研究。(由于3D打印机不稳定,步进电机模块与外壳结合不足导致整体进度卡在百分之80的完成度,我后续完善后继续给大家分享)
1、kei编程软件编写的雷达数据处理部分
#include "Rd_03D.h"
#include "sys.h"
#include "usart3.h"
#include "usart.h"
#include "delay.h"
#include "string.h"
#include "stdlib.h"
#include "math.h"
#include "led.h"
#include "esp8266.h"
#include "uln2003.h"
#include "timer.h"
#include "lcd.h"
#include "exti.h"
unsigned char Radar_wifi_Data[2];
int rada_num=0;
float radar_num=0;
float pi,angle;
u8 radar_find=0,Radar_detection_mode=0,Radar_mode=0,Radar_floag=0,target_bearing=1;
u16 T=0,F=0;
int radar_data[9],radar_transfer[9],y;
u8 Single_Target[]={0xFD,0xFC,0xFB,0xFA,0x02,0x00,0x80,0x00,0x04,0x03,0x02,0x01};
u8 many_Target[]={0xFD,0xFC,0xFB,0xFA,0x02,0x00,0x90,0x00,0x04,0x03,0x02,0x01};
void radar_usart3_data(void)
{
u8 i,j;
if((USART3_RX_STA&0x8000))
{
if(Radar_floag)
{
if(Radar_detection_mode==0)
{
if(USART3_RX_BUF[0]==0xAA&&USART3_RX_BUF[11]==0x01)
{
Flashing();
rada_num=1;
if(radar_find==0)
{
printf("R%dD",rada_num);
delay_ms(100);
radar_find=1;
ESP8266_Send(T_NUM,rada_num);
delay_ms(300);
}
for(i=0,j=0;i<3;i++,j++)
{
radar_data[i]=USART3_RX_BUF[4+i+j]+(USART3_RX_BUF[5+i+j]<<8);
if(radar_data[i]&0x8000)
radar_data[i]=radar_data[i]&0x7fff;
else
radar_data[i]=-radar_data[i];
}
radar_num=pow((radar_data[0]*0.001),2)+pow((radar_data[1]*0.001),2);
radar_num=sqrt(radar_num);
pi=fabs((radar_data[0]*0.001)/(radar_data[1]*0.001));
angle=atan(pi);
angle=(180/3.14)*angle;
if(radar_data[0]<=50&&radar_data[0]>=-50)
target_bearing=1;
else if(radar_data[0]>50)
target_bearing=2;
else
target_bearing=0;
if(pi<0.27)
{
if(abs(radar_data[0]-radar_transfer[0])<200||abs(radar_data[1]-radar_transfer[1])<200)
{
T++;
if(T==100)
{
ESP8266_Send(POS,target_bearing);
delay_ms(300);
ESP8266_Send_float(SPE,radar_data[2]*0.01);
delay_ms(300);
ESP8266_Send_float(SLDE,radar_num);
delay_ms(300);
printf("R-Target locked");
delay_ms(300);
printf("RD%dES%dPT%dG",(int)(radar_num*100),radar_data[2],target_bearing);
T=0;
}
}
else
{
if(T)
T=0;
for(i=0;i<3;i++)
radar_transfer[i]=radar_data[i];
F++;
if(F==5)
{
printf("R-Target locking failed");
F=0;
}
}
}
else
{
T=0;
if(target_bearing==2)
{
//if(INF1_C!=0)
//{
X_move_L(5,10);
y++;
//}
}
else if(target_bearing==0)
{
X_move_R(5,10);
y--;
}
}
}
else if(USART3_RX_BUF[0]==0xAA&&USART3_RX_BUF[11]==0)
{
if(radar_find)
{
ESP8266_Send(POS,1);
delay_ms(300);
ESP8266_Send_float(SPE,0);
delay_ms(300);
ESP8266_Send_float(SLDE,0);
delay_ms(300);
ESP8266_Send(T_NUM,0);
delay_ms(300);
printf("R-The target has disappeared");
radar_find=0;
T=0;
F=0;
Radar_detection_mode=0;
Radar_mode=0;
rada_num=0;
LCD_Radar_clr_Show();
y=Yuntai_Follow(y);
}
}
}
else
{
if(USART3_RX_BUF[0]==0xAA)
{
for(i=0,j=0;i<9;i++,j++)
{
if(i<3)
radar_data[i]=USART3_RX_BUF[4+i+j]+(USART3_RX_BUF[5+i+j]<<8);
else if(i<6)
radar_data[i]=USART3_RX_BUF[6+i+j]+(USART3_RX_BUF[7+i+j]<<8);
else
radar_data[i]=USART3_RX_BUF[8+i+j]+(USART3_RX_BUF[9+i+j]<<8);
if(radar_data[i]&0x8000)
radar_data[i]=radar_data[i]&0x7fff;
else
radar_data[i]=-radar_data[i];
}
if(USART3_RX_BUF[11]==0x01&&USART3_RX_BUF[19]==0&&USART3_RX_BUF[27]==0)
rada_num=1;
else if(USART3_RX_BUF[11]==0x01&&USART3_RX_BUF[19]==0x01&&USART3_RX_BUF[27]==0)
rada_num=2;
else if(USART3_RX_BUF[11]==0x01&&USART3_RX_BUF[19]==0x01&&USART3_RX_BUF[27]==0x01)
rada_num=3;
else
rada_num=0;
if(Time_1s%5==0)
printf("R%dD",rada_num);
}
}
}
}
USART3_RX_STA=0;
}
void Radar_T_F(u8 Radar_RX_DATA)
{
u8 i;
if(Radar_RX_DATA==1)
{
if(Radar_floag==0)
{
LCD_ShowChinese(0,80,"µ¥Ä¿±ê",RED,WHITE,16,0);
LCD_ShowString(48,80,"-",BLACK,WHITE,16,0);
LCD_ShowChinese(56,80,"±ê×¼",RED,WHITE,16,0);
Radar_floag=1;
Radar_detection_mode=0;
Radar_mode=0;
rada_num=0;
radar_find=0;
T=0;
F=0;
y=0;
strat_USART3();
for(i=0;i<12;i++)
MYUSART3_SendData(Single_Target[i]);
delay_ms(100);
printf("Radar successfully turned on");
}
else printf("Radar working");
}
else if(Radar_RX_DATA==0)
{
if(Radar_floag)
{
LCD_Radar_Off_clr_Show();
y=X_Y_Rest();
Radar_floag=0;
Radar_detection_mode=0;
Radar_mode=0;
rada_num=0;
radar_find=0;
T=0;
F=0;
end_USART3();
printf("Radar turned off");
}
else printf("Radar OFF");
}
}
void Radar_mode_set(u8 Radar_RX_DATA)
{
u8 i;
if(Radar_RX_DATA==1)
{
if(Radar_floag==1)
{
if(Radar_detection_mode)
printf("R_Current mode working");
else
{
LCD_ShowString(0,80," ",RED,WHITE,16,0);
LCD_ShowChinese(0,80,"¶à",RED,WHITE,16,0);
Radar_detection_mode=1;
for(i=0;i<12;i++)
MYUSART3_SendData(many_Target[i]);
printf("R_Multi target mode on");
}
}
else printf("");
}
else if(Radar_RX_DATA==0)
{
if(Radar_floag==1)
{
if(Radar_detection_mode==1)
{
LCD_ShowString(0,80," ",RED,WHITE,16,0);
LCD_ShowChinese(0,80,"µ¥",RED,WHITE,16,0);
Radar_detection_mode=0;
for(i=0;i<12;i++)
MYUSART3_SendData(Single_Target[i]);
printf("R_Single target mode on");
}
else printf("R_Current mode working");
}
else printf("");
}
}
void Radar_work_mode_set(u8 Radar_RX_DATA)
{
if(Radar_floag)
{
if(Radar_RX_DATA==0)
{
if(Radar_mode!=0)
{
LCD_ShowString(56,80," ",RED,WHITE,16,0);
LCD_ShowChinese(56,80,"±ê×¼",RED,WHITE,16,0);
Radar_mode=0;
printf("R_Standard mode on");
}
else printf("R_Current mode working");
}
else if(Radar_RX_DATA==1)
{
if(Radar_mode!=1)
{
LCD_ShowString(56,80," ",RED,WHITE,16,0);
LCD_ShowChinese(56,80,"Ó¦¼±",RED,WHITE,16,0);
Radar_mode=1;
printf("R_Emergency defense mode activated");
}
else printf("R_Current mode working");
}
else if(Radar_RX_DATA==2)
{
if(Radar_mode!=2)
{
LCD_ShowString(56,80," ",RED,WHITE,16,0);
LCD_ShowChinese(56,80,"×Ô¶¯",RED,WHITE,16,0);
Radar_mode=2;
printf("R_Automatic attack mode enabled");
}
else printf("R_Current mode working");
}
}
else printf("");
}
void radar_asr_on_off(void)
{
if(USART_RX_BUF[0]==0x01)
{
Radar_T_F(1);
delay_ms(300);
ESP8266_Send(Radar,Radar_floag);
delay_ms(300);
ESP8266_Send(TDM,0);
delay_ms(300);
ESP8266_Send(ROM,0);
delay_ms(300);
}
else if(USART_RX_BUF[0]==0x04)
{
Radar_T_F(0);
ESP8266_Send(Radar,Radar_floag);
delay_ms(300);
ESP8266_Send(TDM,0);
delay_ms(300);
ESP8266_Send(ROM,0);
delay_ms(300);
ESP8266_Send(POS,1);
delay_ms(300);
ESP8266_Send_float(SPE,0);
delay_ms(300);
ESP8266_Send_float(SLDE,0);
delay_ms(300);
ESP8266_Send(T_NUM,0);
delay_ms(300);
}
}
void radar_asr_mode(void)
{
if(USART_RX_BUF[0]==0x02)
{
Radar_mode_set(0);
ESP8266_Send(TDM,Radar_detection_mode);
}
else if(USART_RX_BUF[0]==0x03)
{
Radar_mode_set(1);
ESP8266_Send(TDM,Radar_detection_mode);
}
else if(USART_RX_BUF[0]==0x09)
{
Radar_work_mode_set(1);
ESP8266_Send(ROM,Radar_mode);
}
else if(USART_RX_BUF[0]==0x0B)
{
Radar_work_mode_set(2);
ESP8266_Send(ROM,Radar_mode);
}
else if(USART_RX_BUF[0]==0x0A)
{
Radar_work_mode_set(0);
ESP8266_Send(ROM,Radar_mode);
}
}
这个是关于雷达处理数据的全部代码,里面掺杂了其他wifi、1.8寸显示等其他综合代码,我嫌麻烦一起复制了,只要看void radar_usart3_data(void)这个函数是雷达处理的主要函数。
由于Rd-03D模组通过串口(TTL电平)与外界通信,雷达串口默认波特率为256000,1停止位,无奇偶校验位。雷达输出检测到的目标信息,包括在区域中的x坐标,y坐标,以及目标的速度值(小端模式)。
上报是数据帧格式:
数据示例:AA FF 03 00 0E 03 B1 86 10 00 68 01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 55 CC
红色部分表示目标1的信息,蓝色表示目标2的信息,绿色表示目标3的信息。
本示例展示解析单目标模式下对角度信息进行解析,所以需对单个目标内的数据进行解析(即目标1),其中单个目标具体包含内容如下:
根据目标X,Y坐标数据帧说明可知,若像上述数据示例,模组将目标1的角度数据转换为相关坐标信息的过程展示如下:
目标1x坐标:OxOE+Ox03256= 782
0-782= -782 mm;
目标1y坐标:OxB1+Ox86256 = 34481
34481-2^15= 1713 mm;
我的数据处理思路就是,通过判断X、Y、速度这三个值来确定是否有人,有人话就实时探测跟踪目标并且实时处理数据。在这里我分了三种情况,目标锁定/目标移动过快丢失/目标消失。
当雷达探测到有人,就开始自动追踪。在摄像头的视野范围内移动,只要连续100次目标X/Y移动的幅度不大于200MM,即锁定成功。如果连续5次移动幅度超过200MM即目标移动过快丢失,锁定失败。
如果超过设定的视野范围就会自动跟随目标移动,最终结果也将是失败或者成功锁定,也可能是目标消失。
如果目标突然移动出最大视野范围左右正负60度,即目标消失。
关于这个X轴跟随后续我会再次更新完善。
四、视频演示(只是其中一部分)
视频地址:【STM32与ESP12F:语音交互,雷达探测,WiFi联网,全程演示!】 https://www.bilibili.com/video/BV1Vc411r7Lv/?share_source=copy_web&vd_source=792fb47d93d5a6322849d58c21c7570f
【MOSS小苔藓:它不是你的尾巴,但它的确是个跟屁虫!】 https://www.bilibili.com/video/BV18Q4y1374C/?share_source=copy_web&vd_source=792fb47d93d5a6322849d58c21c7570f
【震撼来袭!MOSS之第十弹:新电路板换装后开机测试体验!】 https://www.bilibili.com/video/BV1JC4y1Y7PN/?share_source=copy_web&vd_source=792fb47d93d5a6322849d58c21c7570f
五、最后说几句
这只是其中一部分,后续我会持续更新,但是由于事情多,估计更新时间不确定。如果更新我会优先在抖音发布,大家可以关注我的抖音号:5946BNYZD
代码我也会慢慢跟随设计的阶段分享。
2024.9.20更新
一、电路板跟新
通过实际测试,稳压模块需要采用直插封装,要不然功率不够。
不过也可以采取只用5V电源,舍弃12V。(这也是现在我准备采用的方式)
测试视频: