[Momentum wheel self-balancing bicycle] STM32_PID (open source - including hardware data)

Momentum Wheel Self Balancing Bike STM32

How to DIY a Self Balancing Bike? The following will share the production content with everyone, welcome to discuss and exchange~.

content

1. Hardware (with Taobao link, the store is uncertain, you can also search and buy by yourself)

1. STM32F103C8T6 minimum system (small blue board)

2. MPU6050 attitude sensor (3.3V power supply)

3. 0.96 inch OLED display (four pins, IIC communication, 3.3V power supply)

4. HC-05 Bluetooth module

5. Ultrasonic ranging module

6. N20 motor and drive (motor selection: DC 12V A12 type)

7. Brushless Motor Momentum Wheel Module

8. Servo

9. 3S model aircraft battery (pay attention to the battery size)

10. Voltage regulator module and switch

11. Wheels and Bearings

12. Frame and steering structure (3D printing)

13. Circuit PCB

2. Software articles

1.main.c

2. PID control algorithm

3. TIM2 interrupt

4. Battery voltage detection

5. OLED display

6. Notes on code reading

3. Links


1. Hardware (with Taobao link, the store is uncertain, you can also search and buy by yourself)

1. STM32F103C8T6 minimum system (small blue board)

watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBAX-aXuuS7lOWwj-iPoOiQnQ==,size_20,color_FFFFFF,t_70,g_se,x_16

2. MPU6050 attitude sensor (3.3V power supply)

watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBAX-aXuuS7lOWwj-iPoOiQnQ==,size_20,color_FFFFFF,t_70,g_se,x_16

3. 0.96 inch OLED display (four pins, IIC communication, 3.3V power supply)

watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBAX-aXuuS7lOWwj-iPoOiQnQ==,size_20,color_FFFFFF,t_70,g_se,x_16

4. HC-05 Bluetooth module

(Serial communication, used to receive trolley motion commands)

Use the tutorial link: https://blog.csdn.net/weixin_44325419/article/details/110727911

watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBAX-aXuuS7lOWwj-iPoOiQnQ==,size_20,color_FFFFFF,t_70,g_se,x_16

5. Ultrasonic ranging module

watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBAX-aXuuS7lOWwj-iPoOiQnQ==,size_20,color_FFFFFF,t_70,g_se,x_16

6. N20 motor and drive (motor selection: DC 12V A12 type)

watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBAX-aXuuS7lOWwj-iPoOiQnQ==,size_20,color_FFFFFF,t_70,g_se,x_16watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBAX-aXuuS7lOWwj-iPoOiQnQ==,size_20,color_FFFFFF,t_70,g_se,x_16

7. Brushless Motor Momentum Wheel Module

The motor has its own drive and photoelectric encoder.

watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBAX-aXuuS7lOWwj-iPoOiQnQ==,size_20,color_FFFFFF,t_70,g_se,x_16

 In this self-balancing bicycle, we use Mabuchi brushless servo motor, built-in drive, support forward and reverse rotation, PWM speed regulation, and with 100-line encoder AB-phase dual-channel signal output.

watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBAX-aXuuS7lOWwj-iPoOiQnQ==,size_20,color_FFFFFF,t_70,g_se,x_16

The wiring diagram of the motor is shown in the figure above. The color of the wire in the actual car may not match the above figure. You should judge it according to the position rather than the color of the wire.

1.) Signal phase A and phase B are encoder pulse output terminals;

2.) The line for forward and reverse switching is directly controlled by the 3.3V level of the pin of the single-chip microcomputer, and there is no problem at all;

3.) The encoder power supply is connected to 3.3V;

4.) PWM is connected to the PWM output of the single-chip microcomputer. To start the operation, we connect the IO port of the single-chip microcomputer, and set it to high level when the motor is initialized;

5.) The negative pole of the power supply is connected to GND, and the positive pole of the power supply is connected to 12V.

8. Servo

The ones used in the video are a little expensive, you can buy cheap ones.

watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBAX-aXuuS7lOWwj-iPoOiQnQ==,size_20,color_FFFFFF,t_70,g_se,x_16

9. 3S model aircraft battery (pay attention to the battery size)

watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBAX-aXuuS7lOWwj-iPoOiQnQ==,size_20,color_FFFFFF,t_70,g_se,x_16

watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBAX-aXuuS7lOWwj-iPoOiQnQ==,size_20,color_FFFFFF,t_70,g_se,x_16

10. Voltage regulator module and switch

Reduce the voltage of the model aircraft battery to 5V to supply power to the microcontroller, steering gear, Bluetooth, ultrasonic, and motor encoder.

11. Wheels and Bearings

Since the rear wheel of the trolley is driven by a belt, in order to reduce friction and make the rear wheel rotate more smoothly, it is necessary to install a miniature bearing on the rear wheel. (Bearings are purchased according to the axle size)

watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBAX-aXuuS7lOWwj-iPoOiQnQ==,size_20,color_FFFFFF,t_70,g_se,x_16watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBAX-aXuuS7lOWwj-iPoOiQnQ==,size_20,color_FFFFFF,t_70,g_se,x_16watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBAX-aXuuS7lOWwj-iPoOiQnQ==,size_20,color_FFFFFF,t_70,g_se,x_16

    The dimensions are as follows:

12. Frame and steering structure (3D printing)

Click the link of station B at the end of the article to follow and leave a message (or email) to get the 3D printing model file of the frame and steering structure

watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBAX-aXuuS7lOWwj-iPoOiQnQ==,size_20,color_FFFFFF,t_70,g_se,x_16

13. Circuit PCB

The above functional modules are integrated on a PCB circuit board (6.5x7.8cm), in order to facilitate welding, the capacitors, resistors and triodes are all in-line components. The author's level is limited, the PCB is for your reference, and the deficiencies can be adjusted and changed by yourself.

Click the link of station B at the end of the article to follow and leave a message (or email) to get the PCB project file watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBAX-aXuuS7lOWwj-iPoOiQnQ==,size_20,color_FFFFFF,t_70,g_se,x_16

2. Software articles

Click the link of station B at the end of the article to follow and leave a message (or email) to get the Keil source code file

1.main.c

#include "sys.h"

float AdcValue;                                    //电池电压数字量
float Pitch,Roll,Yaw;						      //角度
short aacx,aacy,aacz;		                        //加速度传感器原始数据
short gyrox,gyroy,gyroz;	                        //陀螺仪原始数据
int PWM1;
int PWM_MAX=6500,PWM_MIN=-6500;	//PWM限幅变量
int Encoder_Motor;	//编码器数据(速度)

int main(void)
{  
	NVIC_Config();
   	delay_init();
    Led_Init();
    Beep_Init();
    Wave_SRD_Init();
   	uart3_init(9600);
    OLED_Init();			//初始化OLED  
    OLED_Clear();
	adc_Init();
    MOTOR_1_Init();
    MOTOR_2_Init();
    PWM_Init_TIM3(7199,0);//定时器3初始化PWM 10KHZ,用于驱动动量轮电机 
    PWM_Init_TIM2(9999, 143);//定时器2初始化PWM 50HZ,用于驱动舵机
    TIM_SetCompare1(TIM2, 790);//舵机复位
    Init_TIM1(9998,7199);
    Encoder_Init_TIM4(65535,0);
    OLED_ShowString(25,4,"MPU6050...",16);
    MPU_Init();            //MPU6050初始化  
    while(mpu_dmp_init())
 	{
		OLED_ShowString(25,4,"MPU6050 Error",16);
	}  
    OLED_ShowString(25,4,"MPU6050 OK!",16); 
    Beep=1;
    delay_ms(400);
    Beep=0;
    MPU6050_EXTI_Init();
    OLED_Clear();
 	OLED_ShowString(0,0,"Roll :         C",16);
    OLED_ShowString(0,3,"Speed:         R ",16);
    OLED_ShowString(0,6,"Power:        V ",16);    
    

    while(1)
    {	        
        Wave_SRD_Strat();        
        AdcValue=11.09*(3.3*Get_adc_Average(ADC_Channel_4,10)/0x0fff); //ADC值范围为从0-2^12=4095(111111111111)一般情况下对应电压为0-3.3V
        OLED_Showdecimal(55,0,Roll,9,16);  
        OLED_Showdecimal(55,3,Encoder_Motor*0.25,9,16);         
        OLED_Showdecimal(50,6,AdcValue,9,16);       
	}
}

2. PID control algorithm

Click the link of station B at the end of the article to follow and leave a message (or email) to get PID related tutorial materials

The car is more able to achieve upright balance and needs to use two closed-loop controls, namely upright loop (PD control, negative feedback), speed loop (PI control, positive feedback). The code principle and debugging process are basically the same as the two-wheeled balance car. .

Regarding the learning of PID control algorithm, there is a lot of content, and it is not easy to expand in detail. There are abundant online resources, and you can learn by yourself. Here is a recommended article: https://zhuanlan.zhihu.com/p/39573490

3. TIM2 interrupt

In order to prevent the car from being interfered by the ultrasonic obstacle avoidance function during operation and debugging, the ultrasonic obstacle avoidance function can be turned off first. The ultrasonic obstacle avoidance function is implemented in the timer 2 interrupt service function, so the TIM2 interrupt enable can be turned off.

//TIM_ITConfig(TIM2, TIM_IT_Update, ENABLE); //使能TIM2中断,中断模式为更新中断:TIM_IT_Update
void TIM2_IRQHandler()
{   
    static int count=0;
    if(TIM_GetITStatus(TIM2, TIM_IT_Update)==1) //当发生中断时状态寄存器(TIMx_SR)的bit0会被硬件置1
	{
        TIM_ClearITPendingBit(TIM2, TIM_IT_Update); //状态寄存器(TIMx_SR)的bit0置0
        count++;      
        if(Distance<8)              //与障碍物距离小于8cm时,蜂鸣器发出警报病后退
        {
            Beep=1,Led1=0,Led2=0;
            Backward();
            TIM_SetCompare1(TIM2, 790);//舵机复位
        }
        else Beep=0;
        if(count==25)        //TIM2溢出时间为20ms,20x25=500ms,即后退500ms后停止
        {
            Stopped();count=0;           
        }            
	}
}

4. Battery voltage detection

Generally, the power of the model aircraft battery is related to the voltage. Over-discharge will inevitably lead to permanent over-discharge of the battery and damage to the battery. Therefore, it is necessary for us to monitor the change of the battery voltage to approximate the power of the battery. When the battery power is relatively low, remind We charge, the charging time does not exceed 2 and a half hours, so as not to overcharge the battery. For long-term storage, ensure that the voltage of a single cell is about 3.8V, and charge it once a month.

When fully charged for 3S, it is 12.6V, and the voltage is lower than 9.6V when over-discharged.
When fully charged for 2S, it is 8.4V, and the voltage is lower than 7.4V when over-discharged.

watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBAX-aXuuS7lOWwj-iPoOiQnQ==,size_20,color_FFFFFF,t_70,g_se,x_16

Use the built-in ADC of STM32 to measure the battery voltage. The ADC value range is from 0-2^12=4095 (111111111111). Generally, the corresponding voltage is 0-3.3V, while the 3S model aircraft battery voltage is 12V. Direct measurement will burn the microcontroller, so it is necessary to Divide the battery voltage, the schematic diagram is as follows:

20191128115903985.png

A simple analysis shows that after the battery voltage is divided by resistance and depleted to 1/11 of the original value, it is sent to the single-chip ADC for detection, and then the collected voltage value is multiplied by 11 to obtain the actual voltage of the battery. (here is multiplied by 11.09, which can be fine-tuned according to the actual situation)

#include "adc.h"
#include "delay.h"

//ADC初始化函数
void adc_Init()
{
  GPIO_InitTypeDef GPIO_InitStructure; //定义一个引脚初始化的结构体  
  ADC_InitTypeDef ADC_InitStructure; //定义一个ADC初始化的结构体 
  
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE); //使能CPIOB时钟
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1, ENABLE); //使能TIM4时钟
	
	GPIO_InitStructure.GPIO_Pin=GPIO_Pin_4; //引脚0
	GPIO_InitStructure.GPIO_Mode=GPIO_Mode_AIN; //引脚输入输出模式为模拟输入模式
	GPIO_Init(GPIOA, &GPIO_InitStructure); //根据上面设置好的GPIO_InitStructure参数,初始化引脚GPIOA_PIN0

	RCC_ADCCLKConfig(RCC_PCLK2_Div6);   //设置ADC分频因子6 72M/6=12,ADC最大时间不能超过14M
	ADC_DeInit(ADC1);  //复位ADC1,将外设 ADC1 的全部寄存器重设为缺省值
	
	ADC_InitStructure.ADC_Mode = ADC_Mode_Independent;	//ADC工作模式:ADC1和ADC2工作在独立模式
	ADC_InitStructure.ADC_ScanConvMode = DISABLE;	//是否为扫描(一组)模式:否:单通道模式
	ADC_InitStructure.ADC_ContinuousConvMode = DISABLE;	//是否为连续转换模式,否:单次转换模式
	ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None;	//转换由软件而不是外部触发启动
	ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;	//ADC数据对齐模式:右对齐
	ADC_InitStructure.ADC_NbrOfChannel = 1;	//顺序进行规则转换的ADC通道的数目
	ADC_Init(ADC1, &ADC_InitStructure);	//根据ADC_InitStruct中指定的参数初始化外设ADCx的寄存器  
	
	ADC_Cmd(ADC1, ENABLE);
	
	ADC_ResetCalibration(ADC1);	//使能复位校准   
	while(ADC_GetResetCalibrationStatus(ADC1));	//等待复位校准结束
	
	ADC_StartCalibration(ADC1);	 //开启AD校准
	while(ADC_GetCalibrationStatus(ADC1));	 //等待校准结束
	
	ADC_SoftwareStartConvCmd(ADC1, ENABLE);		//使能指定的ADC1的软件转换启动功能
}

//采集ADC值函数,输入参数为ADC通道
u16 Get_adc(u8 chn)
{
	ADC_RegularChannelConfig(ADC1, chn, 1, ADC_SampleTime_239Cycles5 );	//ADC1,chn:ADC通道,第3个参数设置该通道的转换顺序(多通道模式下)
	                                                                  //采样时间为239.5周期=239.5/ADCCLOK,ADCCLOK=72/6MHZ(6代表ADC初始化时的分频系数)		    
  
	ADC_SoftwareStartConvCmd(ADC1, ENABLE);		//使能指定的ADC1的软件转换启动功能	
	 
	while(!ADC_GetFlagStatus(ADC1, ADC_FLAG_EOC ));//等待转换结束
	return ADC_GetConversionValue(ADC1);	//返回最近一次ADC1规则组的转换结果
}

//采集多次ADC值求平均值函数,输入参数为ADC通道和采集次数
u16 Get_adc_Average(u8 chn, u8 times)
{
  u32 temp_val=0;
	u8 t;
	for(t=0;t<times;t++)
	{
		temp_val+=Get_adc(chn);
		delay_ms(5);
	}
	return temp_val/times;
}
AdcValue=11.09*(3.3*Get_adc_Average(ADC_Channel_4,10)/0x0fff); //ADC值范围为从0-2^12=4095(111111111111)一般情况下对应电压为0-3.3V

5. OLED display

Generally, in the data of the OLED display module purchased by Taobao, there is no decimal and positive and negative functions in the display function. Therefore, the following functions are added to the original display function, so that the angle of the car, the speed of the momentum wheel, and the battery voltage can be conveniently displayed in real time.

//显示9位字符,最高位正负,三位整数,第五位小数点,后四位小数部分
//x,y :起点坐标	 
//len :数字的位数
//size:字体大小	 		  
void OLED_Showdecimal(u8 x,u8 y,float num,u8 len,u8 size2)
{         	
	u8 t,temp,len1,temp1;
	float temp2;
	u8 enshow=0;
    if(num < 0)
	{
        OLED_ShowChar(x,y,'0'- 3,size2);
		num =fabs(num);
	}
    else
	OLED_ShowChar(x,y,' ',size2);//第一位显示符号
	temp1 = (int)temp;
	temp2 = num - temp1;
	len1 = len - 6;//len1为整数部分位数,若显示数位需要扩展,修改该行
	OLED_ShowChar(x + size2/2*4,y,'0'- 2,size2);//浮点数的第5位显示小数点
	x = x + size2/2;
	for(t=0;t<len1;t++)//整数部分的显示
	{
		temp=(int)((num/oled_pow(10,len1-t-1)))%10;
		if(enshow==0&&t<(len1-1))
		{
			if(temp==0)
			{
				OLED_ShowChar(x+(size2/2)*t,y,' ',size2);
				continue;
			}else enshow=1; 
		 	 
		}
	 	OLED_ShowChar(x+(size2/2)*t,y,temp+'0',size2); 
	}
	OLED_ShowChar(x+(size2/2)*4,y,((int)(temp2*10)%10) + '0',size2); //小数第一位
	OLED_ShowChar(x+(size2/2)*5,y,((int)(temp2*100)%10) + '0',size2); //小数第2位
//	OLED_ShowChar(x+(size2/2)*6,y,((int)(temp2*1000)%10) + '0',size2); //小数第3位
//	OLED_ShowChar(x+(size2/2)*7,y,((int)(temp2*10000)%10) + '0',size2); //小数第4位
} 

6. Notes on code reading

1.) All header files are included in sys.h, and each .h file includes sys.h for convenient function calls.

#ifndef __SYS_H
#define __SYS_H	
#include "stm32f10x.h"
#include "adc.h"
#include "oled.h"
#include "led.h" 
#include "beep.h"
#include "wave.h"
#include "control.h" 
#include "exti.h" 
#include "mpu6050.h"
#include "inv_mpu.h"
#include "inv_mpu_dmp_motion_driver.h" 
#include "motor.h"
#include "pwm.h"
#include "encoder.h"
#include "usart.h"   				
#include "delay.h"

#include <math.h>
#include <stdlib.h>

2.) Interrupt priority grouping is configured in the sys.c file

#include "sys.h"

/*
  ============================================================================================================================
    NVIC_PriorityGroup   | NVIC_IRQChannelPreemptionPriority | NVIC_IRQChannelSubPriority  | Description
  ============================================================================================================================
   NVIC_PriorityGroup_0  |                0                  |            0-15             |   0 bits for pre-emption priority
                         |                                   |                             |   4 bits for subpriority
  ----------------------------------------------------------------------------------------------------------------------------
   NVIC_PriorityGroup_1  |                0-1                |            0-7              |   1 bits for pre-emption priority
                         |                                   |                             |   3 bits for subpriority
  ----------------------------------------------------------------------------------------------------------------------------    
   NVIC_PriorityGroup_2  |                0-3                |            0-3              |   2 bits for pre-emption priority
                         |                                   |                             |   2 bits for subpriority
  ----------------------------------------------------------------------------------------------------------------------------    
   NVIC_PriorityGroup_3  |                0-7                |            0-1              |   3 bits for pre-emption priority
                         |                                   |                             |   1 bits for subpriority
  ----------------------------------------------------------------------------------------------------------------------------    
   NVIC_PriorityGroup_4  |                0-15               |            0                |   4 bits for pre-emption priority
                         |                                   |                             |   0 bits for subpriority                       
  ============================================================================================================================
*/
void NVIC_Config(void)
{
	NVIC_InitTypeDef NVIC_InitStruct_extiB5;
    NVIC_InitTypeDef NVIC_InitStruct_extiA10;
	NVIC_InitTypeDef NVIC_InitStruct_usart3;
    NVIC_InitTypeDef NVIC_InitStruct_tim2;
    NVIC_InitTypeDef NVIC_InitStruct_tim1;
	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);//4级抢占,4级响应。
	
	//外部中断PB5
	NVIC_InitStruct_extiB5.NVIC_IRQChannel=EXTI9_5_IRQn;
	NVIC_InitStruct_extiB5.NVIC_IRQChannelCmd=ENABLE;
	NVIC_InitStruct_extiB5.NVIC_IRQChannelPreemptionPriority=0;
	NVIC_InitStruct_extiB5.NVIC_IRQChannelSubPriority=0;
	NVIC_Init(&NVIC_InitStruct_extiB5);
	
    //USART3 NVIC 配置
    NVIC_InitStruct_usart3.NVIC_IRQChannel = USART3_IRQn;
	NVIC_InitStruct_usart3.NVIC_IRQChannelPreemptionPriority=1 ;//抢占优先级3
	NVIC_InitStruct_usart3.NVIC_IRQChannelSubPriority = 0;		//子优先级3
	NVIC_InitStruct_usart3.NVIC_IRQChannelCmd = ENABLE;			//IRQ通道使能
	NVIC_Init(&NVIC_InitStruct_usart3);	//根据指定的参数初始化VIC寄存器
    
    // 定时器2中断
    NVIC_InitStruct_tim2.NVIC_IRQChannel=TIM2_IRQn; //属于TIM2中断
	NVIC_InitStruct_tim2.NVIC_IRQChannelCmd=ENABLE; //中断使能
	NVIC_InitStruct_tim2.NVIC_IRQChannelPreemptionPriority=1; //抢占优先级为1级,值越小优先级越高,0级优先级最高
	NVIC_InitStruct_tim2.NVIC_IRQChannelSubPriority=1; //响应优先级为1级,值越小优先级越高,0级优先级最高
	NVIC_Init(&NVIC_InitStruct_tim2); //根据NVIC_InitStruct_tim1的参数初始化VIC寄存器,设置TIM2中断
    
    //外部中断PA10
	NVIC_InitStruct_extiA10.NVIC_IRQChannel=EXTI15_10_IRQn;
	NVIC_InitStruct_extiA10.NVIC_IRQChannelCmd=ENABLE;
	NVIC_InitStruct_extiA10.NVIC_IRQChannelPreemptionPriority=2;
	NVIC_InitStruct_extiA10.NVIC_IRQChannelSubPriority=1;
	NVIC_Init(&NVIC_InitStruct_extiA10);
    
    // 定时器1中断
    NVIC_InitStruct_tim1.NVIC_IRQChannel=TIM1_UP_IRQn; //属于TIM1中断
	NVIC_InitStruct_tim1.NVIC_IRQChannelCmd=ENABLE; //中断使能
	NVIC_InitStruct_tim1.NVIC_IRQChannelPreemptionPriority=2; //抢占优先级为1级,值越小优先级越高,0级优先级最高
	NVIC_InitStruct_tim1.NVIC_IRQChannelSubPriority=2; //响应优先级为1级,值越小优先级越高,0级优先级最高
	NVIC_Init(&NVIC_InitStruct_tim1); //根据NVIC_InitStruct_tim1的参数初始化VIC寄存器,设置TIM2中断
}

3.) After the MCU of STM32F10x series is reset, PA13/14/15 & PB3/4 are configured as JTAG function by default. Sometimes we set these ports as normal I/O ports in order to make full use of the resources of the MCU I/O ports.

When using JLINK to program STM32, you need to use 6 chip pins (take STM32F103C8T6 as an example), namely PB4/JNTRST, PB3/JTDO, PA13/JTMS, PA14/JTCK, PA15/JTDI, NRST. When the IO port resources of the chip are relatively tight, you can choose the SW mode to burn the program. SWD only needs to use PA13 / JTMS, PA14 / JTCK two lines, NREST can be connected or not, the remaining PB4 / JNTRST, PB3 / JTDO and PA15 / JTDI can be used as ordinary IO, but these three ports are of course ordinary When using IO, you need to configure the following first. (Here MPU6050 module uses PB3 and PB4 pins)

mpuiic.c

//初始化IIC
void MPU_IIC_Init(void)
{					     
  GPIO_InitTypeDef  GPIO_InitStructure;
  RCC_APB2PeriphClockCmd( RCC_APB2Periph_AFIO|RCC_APB2Periph_GPIOB,ENABLE); //打开PB口时钟和AFIO复用时钟
  GPIO_PinRemapConfig(GPIO_Remap_SWJ_JTAGDisable,ENABLE); //重映射
		
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3|GPIO_Pin_4;	 // 端口配置
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; 		 //推挽输出
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;		 //IO口速度为50MHz
  GPIO_Init(GPIOB, &GPIO_InitStructure);					 //根据设定参数初始化GPIO 
	
  GPIO_SetBits(GPIOB,GPIO_Pin_3|GPIO_Pin_4);						 //PB3,PB4 输出高	
 
}

3. Links

bilibili_[Momentum Wheel Self-Balancing Bike] STM32_PID (open source - including hardware information) https://www.bilibili.com/video/BV1M3411J77m?share_source=copy_web

Guess you like

Origin blog.csdn.net/weixin_47820462/article/details/122797752