stm32f103c8t6最小系统板四驱蓝牙小车
时间: 2023-10-26 22:06:00 浏览: 129
基于STM32F103C8T6最小系统板的四驱蓝牙小车是一种基于STM32CubeMX的HAL库开发的智能小车,可以通过蓝牙遥控小车运动方向。该小车有以下特点:
1. 采用STM32F103C8T6最小系统板作为主控芯片,具有较高的性能和稳定性。
2. 采用四驱设计,可以实现更加灵活的运动方式。
3. 通过蓝牙遥控小车运动方向,可以实现远程控制。
4. 程序有详细的解释,方便开发者进行二次开发。
该小车的开发可以分为以下几个步骤:
1. 硬件设计:包括电路原理图设计、PCB设计等。
2. 软件设计:包括STM32CubeMX的HAL库开发、蓝牙通信协议设计等。
3. 调试测试:包括硬件调试、软件调试等。
相关问题
STM32F103C8T6制作循迹小车四轮
### STM32F103C8T6 四轮循迹小车教程
#### 硬件连接
对于四轮循迹小车而言,硬件部分主要包括STM32F103C8T6单片机、红外传感器阵列用于检测轨迹线、编码器测量电机转速以及直流电机驱动车辆运动。这些组件之间需建立可靠的电气连接以确保系统稳定运行。
- **电源管理**:为保证各部件正常运作,应提供稳定的供电电压给MCU和其他外设。通常情况下,电池组会向整个电路板供电;而敏感元件如MCU则可能需要额外稳压芯片来获得更纯净的工作条件[^1]。
- **信号传输线路**:从红外发射接收头到处理器之间的数据通信路径至关重要。建议使用短且屏蔽良好的导线减少干扰影响精度。同样地,在反馈速度信息回传至CPU时也应注意布线质量[^2]。
- **接口定义**
- 将多个红外反射式光电开关均匀分布于底盘前端两侧边缘处形成探测带;
- 连接上述器件的数据端口分别接入指定GPIO引脚上以便读取状态变化情况;
- 对于每台马达来说,则要将其使能端子与PWM输出通道关联起来从而实现调速目的。
```cpp
// GPIO初始化配置示例代码 (假设使用HAL库)
__HAL_RCC_GPIOA_CLK_ENABLE(); // 开启PA口时钟
GPIO_InitTypeDef GPIO_InitStruct = {0};
GPIO_InitStruct.Pin = GPIO_PIN_0 | GPIO_PIN_1; // 定义使用的管脚编号
GPIO_InitStruct.Mode = GPIO_MODE_INPUT; // 设置输入模式
GPIO_InitStruct.Pull = GPIO_NOPULL; // 不启用上下拉电阻
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
__HAL_RCC_TIM2_CLK_ENABLE();
TIM_HandleTypeDef htim2;
htim2.Instance = TIM2;
htim2.Init.Prescaler = 79;
htim2.Init.CounterMode = TIM_COUNTERMODE_UP;
htim2.Init.Period = 999;
htim2.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
if (HAL_TIM_PWM_Init(&htim2) != HAL_OK){
Error_Handler();
}
```
#### 控制算法
为了提高行驶过程中的稳定性和平顺度,可以引入PID调节机制对实际位置偏差做出响应调整。具体来讲就是依据当前时刻所获取的位置误差计算出相应的校正量作用于执行机构之上直至达到预期目标为止。
- **参数整定方法**
鉴于不同应用场景下最佳系数不尽相同因此有必要针对特定环境反复试验优化Kp(比例增益),Ki(积分时间常数), Kd(微分提前角)三个关键因子直到取得满意效果为止。
- **程序逻辑结构**
下面给出一段简化版伪代码描述了如何利用PID控制器完成直线跟踪任务:
```cpp
float Setpoint = 0.0f; /* 设定点 */
float Input = 0.0f; /* 测量值 */
float Output = 0.0f; /* 输出控制量 */
double lastTime = millis();
void loop() {
double currentTime = millis();
double deltaTime = (currentTime - lastTime)/1000;
// 获取当前位置偏移量作为Input变量赋值
myPID.Compute(); /* 计算新的Output值 */
setMotorSpeed(Output);/* 应用此结果改变左右两侧行驶速率差异*/
lastTime = currentTime;
}
class PID{
public:
void Compute(){
error = Setpoint - Input;
Pout = kp * error;
Iout += ki * error * dt;
Dout = kd * ((error-lastError)/dt);
Output = Pout + Iout + Dout;
lastError = error;
}
private:
float kp=1,kd=0.1,ki=0.05;
float pOut,iOut,dOut,lastError,error;
};
```
四编码器小车pid控制程序,要求用stm32 f103c8t6标准库
### 使用STM32 F103C8T6标准库实现四编码器小车PID控制的程序代码及开发指导
#### 一、硬件配置
STM32F103C8T6是一款基于ARM Cortex-M3内核的微控制器,适用于嵌入式应用中的复杂控制场景。为了实现四轮独立驱动的小车控制系统,需配备四个直流电机及其对应的L298N或TB6612电机驱动模块,并连接四个旋转编码器以采集各电机的速度反馈数据[^1]。
#### 二、软件环境搭建
本项目采用STM32的标准外设库(Standard Peripheral Library),而非HAL库。以下是必要的准备工作:
- 安装并配置Keil MDK或其他支持标准库编译的IDE。
- 下载对应版本的STM32 Standard Peripheral Drivers包。
- 配置GPIO端口作为PWM输出和编码器输入接口。
#### 三、初始化设置
##### 1. GPIO与TIM初始化
每个电机都需要一个PWM信号来调节转速,因此需要分配多个定时器资源。例如,可以使用TIM2至TIM5分别生成四路PWM波形:
```c
void TIM_PWM_Init(uint16_t arr, uint16_t psc) {
GPIO_InitTypeDef GPIO_InitStruct;
TIM_TimeBaseInitTypeDef TIM_BaseStruct;
TIM_OCInitTypeDef TIM_OCInitStruct;
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2 | RCC_APB1Periph_TIM3 |
RCC_APB1Periph_TIM4 | RCC_APB1Periph_TIM5, ENABLE);
// 配置GPIO模式为复用推挽输出
GPIO_InitStruct.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_1; // 假设TIM2_CH1/CH2
GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA, &GPIO_InitStruct);
// 初始化TIM基础参数
TIM_BaseStruct.TIM_Period = arr;
TIM_BaseStruct.TIM_Prescaler = psc;
TIM_BaseStruct.TIM_ClockDivision = TIM_CKD_DIV1;
TIM_BaseStruct.TIM_CounterMode = TIM_CounterMode_Up;
TIM_TimeBaseInit(TIM2, &TIM_BaseStruct);
// 输出比较模式配置
TIM_OCInitStruct.TIM_OCMode = TIM_OCMODE_PWM1;
TIM_OCInitStruct.TIM_OutputState = TIM_OutputState_Enable;
TIM_OCInitStruct.TIM_Pulse = 0; // 初始占空比为0%
TIM_OCInitStruct.TIM_OCPolarity = TIM_OCPolarity_High;
TIM_OC1Init(TIM2, &TIM_OCInitStruct);
TIM_Cmd(TIM2, ENABLE);
}
```
##### 2. 编码器读取
利用外部中断捕获编码器脉冲变化,从而计算当前电机的实际转速。假设每圈产生若干个计数点,则可通过单位时间内的增量估算角速度。
```c
volatile int encoder_counts[4]; // 存储四个编码器累计值
// 中断服务例程模板
void EXTIx_IRQHandler() {
if (EXTI_GetITStatus(EXTI_LineX)) { // 替换实际使用的线号
encoder_counts[index]++;
EXTI_ClearITPendingBit(EXTI_LineX);
}
}
void Encoder_GPIO_Configuration() {
GPIO_InitTypeDef GPIO_InitStruct;
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOA, ENABLE);
GPIO_InitStruct.GPIO_Pin = GPIO_Pin_X; // 对应编码器A/B相接脚
GPIO_InitStruct.GPIO_Mode = GPIO_Mode_IN_FLOATING;
GPIO_Init(GPIOA, &GPIO_InitStruct);
NVIC_InitTypeDef NVIC_InitStruct;
NVIC_InitStruct.NVIC_IRQChannel = EXTIx_IRQn;
NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority = 0;
NVIC_InitStruct.NVIC_IRQChannelSubPriority = 0;
NVIC_InitStruct.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStruct);
}
```
#### 四、PID算法实现
定义结构体存储比例增益(Kp),积分增益(Ki),以及微分增益(Kd)等参数;同时记录目标速度(Target_Speed)、误差(error)等相关变量以便动态调整输出量。
```c
typedef struct {
float Kp, Ki, Kd;
float Setpoint, Input, Output;
} PID_Controller;
float Compute_PID(PID_Controller *pid_ctrlr, float measured_value) {
static float prev_error = 0.0f;
float error = pid_ctrlr->Setpoint - measured_value;
pid_ctrlr->Output += pid_ctrlr->Ki * error;
pid_ctrlr->Output += pid_ctrlr->Kp * error +
pid_ctrlr->Kd * ((error - prev_error));
prev_error = error;
return pid_ctrlr->Output;
}
```
调用`Compute_PID()`函数传入实时测量到的轮子转速后即可得到新的PWM占空比数值,再将其赋给相应通道完成闭环调控过程。
---
####
阅读全文
相关推荐














