STM32F103C8T6 HAL库——从零开始的制作平衡小车生活


最近买了个平衡小车,为了圆我PID梦,买来玩玩,废话不多说,直接开搞

第一步:让小车的轮子转起来

我用的电机是TB6612FNG,想详细了解的话直接去搜手册,给他输出两路PWM还要两个引脚进行高低电平的转换就可以设置前进或者后退了,规则如下
在这里插入图片描述
看一下引脚图吧
在这里插入图片描述
引脚连接:

PWMAPA11
PWMBPA8
AIN1PB13
AIN2PB12
BIN1PB14
BIN2PB15

下面开始配置CUBE
首先是SYS:
在这里插入图片描述
其次是时钟:
在这里插入图片描述
在这里插入图片描述

下面开始引脚的设置:
在这里插入图片描述
用定时器1,10Hz就够了
在这里插入图片描述
生成:
在这里插入图片描述

代码部分:
main.h

/* USER CODE BEGIN Private defines */
#define AIN2_Pin GPIO_PIN_12
#define AIN2_GPIO_Port GPIOB
#define AIN1_Pin GPIO_PIN_13
#define AIN1_GPIO_Port GPIOB

#define BIN2_Pin GPIO_PIN_14
#define BIN2_GPIO_Port GPIOB
#define BIN1_Pin GPIO_PIN_15
#define BIN1_GPIO_Port GPIOB
/* USER CODE END Private defines */

main.c

/* USER CODE BEGIN 2 */
	HAL_TIM_PWM_Start(&htim1,TIM_CHANNEL_1);//开启TIM1_CH1
  	HAL_TIM_PWM_Start(&htim1,TIM_CHANNEL_4);//开启TIM1_CH4
	HAL_GPIO_WritePin(AIN1_GPIO_Port,AIN1_Pin,GPIO_PIN_RESET);//AIN1为0
	HAL_GPIO_WritePin(AIN2_GPIO_Port,AIN2_Pin,GPIO_PIN_SET);//AIN2位1,反转
	HAL_GPIO_WritePin(BIN1_GPIO_Port,BIN1_Pin,GPIO_PIN_RESET);//BIN1为0
	HAL_GPIO_WritePin(BIN2_GPIO_Port,BIN2_Pin,GPIO_PIN_SET);//BIN2位1,反转
  /* USER CODE END 2 */
 /* USER CODE BEGIN 3 */
		HAL_GPIO_WritePin(AIN1_GPIO_Port,AIN1_Pin,GPIO_PIN_RESET);
		HAL_GPIO_WritePin(AIN2_GPIO_Port,AIN2_Pin,GPIO_PIN_SET);
		HAL_GPIO_WritePin(BIN1_GPIO_Port,BIN1_Pin,GPIO_PIN_RESET);
		HAL_GPIO_WritePin(BIN2_GPIO_Port,BIN2_Pin,GPIO_PIN_SET);
		for(int i=0;i<7100;i++)
		{
			__HAL_TIM_SET_COMPARE(&htim1,TIM_CHANNEL_4,i);//让轮子转起来
			HAL_Delay(1);
		}
		for(int j=7100;j>0;j--)
		{
			__HAL_TIM_SET_COMPARE(&htim1,TIM_CHANNEL_4,j);
			HAL_Delay(1);
		}
		for(int i=0;i<7100;i++)
		{
			__HAL_TIM_SET_COMPARE(&htim1,TIM_CHANNEL_1,i);
			HAL_Delay(1);
		}
		for(int j=7100;j>0;j--)
		{
			__HAL_TIM_SET_COMPARE(&htim1,TIM_CHANNEL_1,j);
			HAL_Delay(1);
		}
  }
  /* USER CODE END 3 */

第二步:用编码器测出小车的速度

先看原理图
在这里插入图片描述
PA0和PA1,PA6和PA7分别是小车的编码器引脚,所以我们在cunbe中将这四个引脚设置为Encoder模式
在这里插入图片描述
在cube中设置好编码器之后,我们再设置好串口,异步通信,再打开中断
在这里插入图片描述
首先开启编码器

void Encoder_Start(void)   //启动两个编码器. 而编码器初始化HAL_TIM_Encoder_Init()和HAL_TIM_Encoder_MspInit()在main()函数中调用的MX_TIM2_Init()中。
{
	__HAL_TIM_SET_COUNTER(&htim2,0);   //用带参宏设置编码器的初始值为0(涉及正反转的需要)
	__HAL_TIM_SET_COUNTER(&htim3,0);

	HAL_TIM_Encoder_Start_IT(&htim2,TIM_CHANNEL_ALL);   //开启编码器的中断模式,两个定时器通道TI1和TI2是每个编码器的两个信号采集通道.
	HAL_TIM_Encoder_Start_IT(&htim3,TIM_CHANNEL_ALL);

	HAL_TIM_Encoder_Start(&htim2,TIM_CHANNEL_ALL);  //开启两个编码器
	HAL_TIM_Encoder_Start(&htim3,TIM_CHANNEL_ALL);
	
}

读取编码器速度值

int Read_Speed(int TIMx)
{
	int Encoder_Value = 0;
	switch(TIMx)
	{
		case 2: 
			Encoder_Value =(short) __HAL_TIM_GET_COUNTER(&htim2);     //保存编码器计数器的值
			__HAL_TIM_SET_COUNTER(&htim2,0);                   //保存之后要清零,以便下次继续读取.另外每次清零后采样值减0,直接用单位时间的话就可以得出速度信息了.不要麻烦还要减去初值了.
			break;

		case 3: 
			Encoder_Value =(short) __HAL_TIM_GET_COUNTER(&htim3);
			__HAL_TIM_SET_COUNTER(&htim3,0);
			break;
		
		default:
			Encoder_Value = 0;
	}	
	return Encoder_Value;
}

这里是主函数,记得定义encoder2和encoder3

  /* USER CODE BEGIN WHILE */
  while (1)
  {
    /* USER CODE END WHILE */
    /* USER CODE BEGIN 3 */
	encoder2=Read_Speed(2);
	encoder3=Read_Speed(3);
	printf("A轮=%d,B轮=%d\n",encoder2,encoder3);
  }
}

输出结果,因为是拿手转的,只能一只手转轮子:
在这里插入图片描述

第三步:读取MPU6050的数据值

接下来就是最难的MPU6050了,我这里就不详细讲了,因为我自己对底层也不是很了解

左边我们可以看到XYZ的加速度,和XYZ陀螺仪数值,他们经过ADC转换后的数值通过IIC可以直接输出,但是数值就是纯数值,并不是角度值,然后就去DMP了,DMP在输出去FIMO,我理解就是,可以把MPU6050读取的这些东西,变成四元数,然后再通过IIC输出,就可以变成角度值了

在这里插入图片描述
首先我们在CUBE中配置好IIC的SDA线和SCL线
在这里插入图片描述
在这里插入图片描述
MPU6050的读写程序我就不展示了,因为这些从网络上都能找到,我用的是正点原子的,需要注意的就是我这里用的是硬件的HAL库IIC,之前我们老师说硬件的IIC有点bug,让我们用软件的,但是我试了试硬件的IIC,发现也挺好用的,就不用软件的了

读取结果:
在这里插入图片描述
可以看到欧拉角的角度值,这样就可以去调整小车的姿态了

第四步:PID

更新时间不确定(在实习和忙学术)

评论 112
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Sol-itude

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值