风扇可调三档,OLED显示速度和档数且会有LED档指示灯。分别有两个按键控制加档和减档。
一、模组图片:直流电机模块
直流电机是一种将电能转换为机械能的装置,有两个电极,当电极正接时,电机正转,当电极反接时,电机反转
直流电机属于大功率器件,GPIO口无法直接驱动,需要配合电机驱动电路来操作。
TB6612是一款双路H桥型的直流电机驱动芯片,可以驱动两个直流电机并且控制其转速和方向。
直流电机是一种将电能转换为机械能的设备,主要通过控制电压和电流来调节其速度和转向。电机的速度可以通过改变供电的电压或电流来控制,而转向可以通过改变电流方向来实现。电机通常由永磁体和旋转的电枢(带导体线圈的部分)组成,电流通过电枢导体产生磁场与永磁体互相作用产生力矩,从而驱动电机旋转。
因为直流电机属于大功率器件,GPIO无法直接驱动,所以需要配合电机驱动。所以电机驱动是介于控制器(如微控制器)和电机之间的设备,作为电机的电源管理系统。驱动器负责接收低电压控制信号,并转换成可以直接驱动电机的高电压功率信号。驱动器能够控制电机的启动、停止、速度、扭矩和旋转方向。本次实验使用TB6612直流电机驱动模块。
二、TB6612模块
TB6612是一款小型、高效的电机驱动芯片,适用于小型直流电机或步进电机。它可以处理较高的电流和电压,同时还提供过热保护和欠压锁定功能。TB6612芯片具有两个H桥,可以驱动两个电机或一个双向电机。
驱动电路中使用的H桥结构用于控制电机的旋转方向。通过在H桥的四个开关之间切换(这些开关通常是晶体管或MOSFET),可以改变流经电机的电流方向。H桥也可以用来实现PWM调速,即通过调节开关的开合时间比例来控制电机的平均电压和速度。
VM: 电机供电输入,通常需要提供4.5-10V的直流电压。
VCC: 逻辑供电输入,用于IC内部逻辑电路,电压范围通常是2.7-5.5V,和主控使用同一个电源。
GND: 接地引脚。
STBY: 待机模式控制引脚,当此引脚为高电平时,电机驱动器工作;为低电平时,驱动器处于待机状态。如果不需要这个功能直接接3.3v即可。
PWMA/B: PWM信号输入,用于控制电机的速度。
AIN1/A2, BIN1/B2: 电机旋转方向控制输入,通过改变这些引脚的高低电平,可以控制电机的旋转方向。这两个信号和PWMA一起,通过低功率的控制信号来控制VM将电路输入给AO端,实现控制大功率设备。
AO1/AO2, BO1/BO2: 连接到电机的输出引脚。
三、代码部分
PWM信号在电机控制中的应用主要表现在精确控制电机的转速和转矩上。在直流电机控制中,通过调整PWM信号的占空比来改变电机两端的平均电压,从而实现对电机转速的连续可调。同样地,对于交流电机如步进电机,PWM可以控制其相位切换的时间点,进而控制电机的转矩和速度。
调整PWM信号的占空比可以通过修改定时器的捕获比较寄存器(Capture/Compare Register)来实现。每次定时器重载时,捕获比较寄存器中的值将决定PWM信号的高电平持续时间,从而改变占空比。
PWM.c
void PWM_Init(void)
{
/*开启时钟*/
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
/*GPIO初始化*/
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA, &GPIO_InitStructure);
/*配置时钟源*/
TIM_InternalClockConfig(TIM2);
/*时基单元初始化*/
TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure; //定义结构体变量
TIM_TimeBaseInitStructure.TIM_ClockDivision = TIM_CKD_DIV1;
TIM_TimeBaseInitStructure.TIM_CounterMode = TIM_CounterMode_Up;
TIM_TimeBaseInitStructure.TIM_Period = 100 - 1;
TIM_TimeBaseInitStructure.TIM_Prescaler = 36 - 1;
TIM_TimeBaseInitStructure.TIM_RepetitionCounter = 0;
TIM_TimeBaseInit(TIM2, &TIM_TimeBaseInitStructure);
/*输出比较初始化*/
TIM_OCInitTypeDef TIM_OCInitStructure; //定义结构体变量
TIM_OCStructInit(&TIM_OCInitStructure); //结构体初始化
TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1; //输出比较模 TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High; //输出极性,选择为高,若选择极性为低,则输出高低电平取反
TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable; //输出使能
TIM_OCInitStructure.TIM_Pulse = 0; //初始的CCR值
TIM_OC3Init(TIM2, &TIM_OCInitStructure); //将结构体变量交给TIM_OC3Init,配置TIM2的输出比较通道3
/*TIM使能*/
TIM_Cmd(TIM2, ENABLE); //使能TIM2,定时器开始运行
}
/**
* 函 数:PWM设置CCR
* 参 数:Compare 要写入的CCR的值,范围:0~100
* 返 回 值:无
* 注意事项:CCR和ARR共同决定占空比,此函数仅设置CCR的值,并不直接是占空比
* 占空比Duty = CCR / (ARR + 1)
*/
void PWM_SetCompare3(uint16_t Compare)
{
TIM_SetCompare3(TIM2, Compare); //设置CCR3的值
}
Motor.c
void Motor_Init(void)
{
/*开启时钟*/
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE); //开启GPIOA的时钟
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4 | GPIO_Pin_5;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA, &GPIO_InitStructure); //将PA4和PA5引脚初始化为推挽输出
PWM_Init(); //初始化直流电机的底层PWM
}
void Motor_SetSpeed(int8_t Speed)
{
GPIO_SetBits(GPIOA, GPIO_Pin_4); //PA4置高电平
GPIO_ResetBits(GPIOA, GPIO_Pin_5); //PA5置低电平,设置方向为正转
PWM_SetCompare3(Speed); //PWM设置为速度值
}
调节档数n时每档指示灯会亮起,我设置一档指示灯为白灯,speed为20,二档指示灯为蓝灯,speed为40,三档指示灯为红灯,speed为60。通过按键一来实现加档,按键二实现减档。OLED显示每档速度和档数。
首先判断按键键码,当键码为1时,speed+20,档数加一,同时将档数的值减一赋给i(后面点亮该档位指示灯时熄灭上一档位指示灯),如果speed大于60,则令speed=0,n=0。当键码为2时,speed-20,档数减一,同时将档数的值减一赋给i,如果speed小于0,则令speed=60,n=3。将speed值赋给PWM的CCR值。设置LED_set[]数组,将端口值写入数组中,最后置该档灯GPIO口为高电平,同时置上一档灯GPIO口为低电平。
Main.c
uint8_t KeyNum; //定义用于接收按键键码的变量
int8_t Speed; //定义速度变量
int32_t LED_set[]={GPIO_Pin_1,GPIO_Pin_8,GPIO_Pin_9,GPIO_Pin_10};//LED指示灯数组
int8_t n=0,i=0;
int main(void)
{
/*模块初始化*/
OLED_Init(); //OLED初始化
Motor_Init(); //直流电机初始化
Key_Init(); //按键初始化
LED_Init(); //LED初始化
/*显示静态字符串*/
OLED_ShowString(1, 1, "Speed:"); //1行1列显示字符串Speed:
OLED_ShowString(2,1,"n:"); //2行1列显示字符串n:
while (1)
{
KeyNum = Key_GetNum(); //获取按键键码
/*加按键*/
if (KeyNum == 1) //按键1按下
{
Speed += 20; //速度变量自增20
i=n;
n+=1;
if (Speed > 60) //速度变量超过后
{
Speed = 0; //速度变量变为0
n=0;
}
}
/*减按键*/
if (KeyNum == 2) //按键2按下
{
Speed -= 20; //速度变量自减20
i=n;
n-=1;
if (Speed < 0) //速度变量低于0后
{
Speed = 60; //速度变量变为60
n=3;
}
}
Motor_SetSpeed(Speed); //设置直流电机的速度为速度变量
OLED_ShowSignedNum(1, 7, Speed, 3); //OLED显示速度变量
OLED_ShowNum(2,3,n,2); //OLED显示档数变量
GPIO_SetBits(GPIOA,LED_set[n]); //n档风扇指示灯亮起
GPIO_ResetBits(GPIOA, LED_set[i]);//上一档风扇指示灯熄灭
}
}