STM32 uses sr04 ultrasonic one-receiver-one range measurement to achieve spatial positioning.

Demo video

Ultrasonic module used

Display of results

 The three modules used send ultrasonic waves at different locations, and then the receiving end obtains the distance between the receiving end and the three transmitting ends. If the coordinates of the three transmitting ends are known, the coordinates of the receiving end can be calculated based on the three distance values.

The sending end uses an stm32 to control, and the synchronization signal sent and received uses infrared. After the receiving end receives the infrared signal, it starts a 1us timer. Each ultrasonic module at the sending end sends an interval of 40ms (to avoid the interval time being too short, the sound wave reflection interference).

Here you need to use a logic analyzer or oscilloscope to check the time difference between sending and receiving, make fine adjustments, and eliminate some interference signals.

Infrared module

The receiving end does not use the echo pin of the module because the module itself has anti-interference measures. If trig is not used to send, the echo will not return a signal. If you want to directly obtain the received signal, you can connect the pin in the picture. 

 Timing of each signal

 

 The received ultrasonic signal is a 40k rectangular wave. You need to pay attention to other interference signals.

The time from sending to receiving the infrared signal is basically the same, and after each infrared transmission is completed, an ultrasonic wave is sent. We adjust the time at the receiving end, fix a delay from receiving the infrared signal, and start timing when the ultrasonic wave is sent, until It will stop when receiving the ultrasonic signal. The time can be calculated by calculating the timer count value * counting period, and then multiplied by the speed of sound to calculate the distance.

Sender implementation code:

standard library

        TIM_Cmd(TIM3, ENABLE);
		TIM3->CNT=0;//开始计时

		TIM_Cmd(TIM2, ENABLE);
		TIM_SetCompare2(TIM2,13);//红外发送信号,38khz
	
		while(TIM3->CNT<500);
		TIM_SetCompare2(TIM2,0);//停止发送,发送不能太长,也不能太短,
        //太长没必要,太短会发送不成功
	
		GPIO_WriteBit(GPIOB,GPIO_Pin_0,Bit_SET);//超声波模块1发送引脚,trig
	
		TIM3->CNT=0;
		while(TIM3->CNT<15);
		GPIO_WriteBit(GPIOB,GPIO_Pin_0,Bit_RESET);//15us后关闭,要超过10us
		TIM3->CNT=0;
		while(TIM3->CNT<40000);//等待40ms
	
		GPIO_WriteBit(GPIOB,GPIO_Pin_1,Bit_SET);//超声波模块1发送引脚,trig
		TIM3->CNT=0;
		while(TIM3->CNT<15);
		GPIO_WriteBit(GPIOB,GPIO_Pin_1,Bit_RESET);//15us后关闭
		TIM3->CNT=0;
		while(TIM3->CNT<40000);
		
		LED3=1;
		TIM3->CNT=0;
		while(TIM3->CNT<15);
		LED3=0;
		TIM3->CNT=0;
		while(TIM3->CNT<40000);
	
		TIM_Cmd(TIM3, DISABLE);

hal library

        htim2.Instance->ARR=26-1;//设置频率为38k,具体看芯片时钟
		htim2.Instance->CNT=0;
		htim2.Instance->CCR4=0;
		HAL_TIM_PWM_Start(&htim2, TIM_CHANNEL_4);
		HAL_TIM_Base_Start(&htim3);//开启计时,周期为1us
		__HAL_TIM_SetCompare(&htim2, TIM_CHANNEL_4,13);//给红外发送模块38khz
		
		htim3.Instance->CNT=0;
		while(htim3.Instance->CNT<500);//实际情况可修改发送时长
		
		htim2.Instance->CCR4=0;//停止红外信号
		HAL_TIM_Base_Stop(&htim3);
		//ir_send
		
		
		
		HAL_TIM_Base_Start(&htim3);
		HAL_GPIO_WritePin(trig4_GPIO_Port,trig4_Pin,GPIO_PIN_SET);
		htim3.Instance->CNT=0;
		while(htim3.Instance->CNT<15);
		HAL_GPIO_WritePin(trig4_GPIO_Port,trig4_Pin,GPIO_PIN_RESET);
		HAL_TIM_Base_Stop(&htim3);//15us高电平发送

		HAL_TIM_Base_Start(&htim3);
		htim3.Instance->CNT=0;
		while(htim3.Instance->CNT<40000);//等待40us
		HAL_TIM_Base_Stop(&htim3);
		
		
		HAL_TIM_Base_Start(&htim3);
		HAL_GPIO_WritePin(trig2_GPIO_Port,trig2_Pin,GPIO_PIN_SET);
		htim3.Instance->CNT=0;
		while(htim3.Instance->CNT<15);
		HAL_GPIO_WritePin(trig2_GPIO_Port,trig2_Pin,GPIO_PIN_RESET);
		HAL_TIM_Base_Stop(&htim3);//15us高电平发送

		HAL_TIM_Base_Start(&htim3);
		htim3.Instance->CNT=0;
		while(htim3.Instance->CNT<40000);//等待40us
		HAL_TIM_Base_Stop(&htim3);
		

take over

standard library

void EXTI15_10_IRQHandler(void)//中断处理红外同步信号
{
	//读取GPIO14中断线的状态
	if(EXTI_GetITStatus(EXTI_Line10) == SET)
	{
		EXTI_ClearITPendingBit(EXTI_Line10);
		get_dis();
		
		
	}
}
unsigned char i_get=0;
extern int dis_1,dis_2,dis_3;
int count_temp=0;
int t_assist[2]={-30,-1950};//后两个模块接收计时校准参数
void get_dis()
{
		
		t_count=0;
	    int i, j, N;
		i_get=0;
		
		TIM_Cmd(TIM2, ENABLE);
		TIM2->CNT=0;
		while(TIM2->CNT<270);//计时校准延时,实际可能需要用示波器或者逻辑分析仪查看

		start_listen:
		TIM2->CNT=0;//开始计时
		while(GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_14)==Bit_SET&&TIM2->CNT<10000);//持续高电平等待低电平脉冲,也就是滤除干扰
		sr04_dis[i_get]=TIM2->CNT;
		TIM2->CNT=0;
		goon://这里goto语句是两个及以上的发送模块时需要
		while(GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_14)==Bit_RESET)//记录低电平脉冲时间
		if(TIM2->CNT>10||TIM2->CNT<4) goto goon;//过低或过高都重计
		
		sr04_dis[i_get]+=(TIM2->CNT>20000)? 20000:TIM2->CNT;
		t_count=sr04_dis[i_get];
		sr04_dis[i_get]-=7;
		i_get++;
		
		TIM2->CNT=0;
		while(TIM2->CNT<(40000-t_count-t_assist[i_get-1]));//等待40ms
		if(i_get<3) goto start_listen;
		end:
		;
}

 Hal library, there is a problem with this and it has not been modified yet. You can refer to the code modification of the standard library.

float get_dis()
{
	i_get=0;

	t_count=0;
	 int i, j, N;
	while(i_get++<5)
	{
		HAL_TIM_Base_Start(&htim3);
		HAL_GPIO_WritePin(GPIOA,GPIO_PIN_11,GPIO_PIN_SET);
		htim3.Instance->CNT=0;
		while(htim3.Instance->CNT<15);
		HAL_GPIO_WritePin(GPIOA,GPIO_PIN_11,GPIO_PIN_RESET);
		
		while(HAL_GPIO_ReadPin(GPIOA,GPIO_PIN_12)==GPIO_PIN_RESET&&htim3.Instance->CNT<65000);
		htim3.Instance->CNT=0;
		while(HAL_GPIO_ReadPin(GPIOA,GPIO_PIN_12)==GPIO_PIN_SET);
		while(HAL_GPIO_ReadPin(GPIOA,GPIO_PIN_12)==GPIO_PIN_SET);
		while(HAL_GPIO_ReadPin(GPIOA,GPIO_PIN_12)==GPIO_PIN_SET);
		while(HAL_GPIO_ReadPin(GPIOA,GPIO_PIN_12)==GPIO_PIN_SET);
		while(HAL_GPIO_ReadPin(GPIOA,GPIO_PIN_12)==GPIO_PIN_SET);
		HAL_TIM_Base_Stop(&htim3);
		t_count+=(htim3.Instance->CNT>35000)? 35000:htim3.Instance->CNT;
		HAL_Delay(20);
	}

	sr04_dis=t_count/5.0;
	return sr04_dis;
	
}

Guess you like

Origin blog.csdn.net/hhcgn/article/details/130623140