28BYJ-48步进驱动
学单片机的基本都会学习28BYJ-48这个步进的驱动
问题描述
平常这个步进的单片机驱动例子多为四拍或八拍电平驱动,但运行噪音较大,下文使用pwm实现细分驱动
参看此文
原因分析:
噪音来源于机械间隙,以及每步的旋转角度
解决方案:
将电机的高低电平驱动,转变为pwm脉冲驱动。
以stm32F407为例
时钟配置
htim8.Instance = TIM8;
htim8.Init.Prescaler = 41;
htim8.Init.CounterMode = TIM_COUNTERMODE_UP;
htim8.Init.Period = 100;
htim8.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
htim8.Init.RepetitionCounter = 0;
sConfigOC.OCMode = TIM_OCMODE_PWM1;
sConfigOC.Pulse = 100;
sConfigOC.OCPolarity = TIM_OCPOLARITY_HIGH;
sConfigOC.OCNPolarity = TIM_OCNPOLARITY_HIGH;
sConfigOC.OCFastMode = TIM_OCFAST_DISABLE;
sConfigOC.OCIdleState = TIM_OCIDLESTATE_RESET;
sConfigOC.OCNIdleState = TIM_OCNIDLESTATE_RESET;
中断函数
volatile uint8_t pwm_count=0;
volatile uint16_t indexWave1[]={2 , 3 , 5 , 7 , 9 , 10 , 12 , 14 , 16 , 17 , 19 , 21 , 22 , 24 , 26 , 28 , 29 , 31 , 33 , 34 , 36 , 37 , 39 , 41 , 42 , 44 , 45 , 47 , 48 , 50 , 52 , 53 , 54 , 56 , 57 , 59 , 60 , 62 , 63 , 64 , 66 , 67 , 68 , 69 , 71 , 72 , 73 , 74 , 75 , 77 , 78 , 79 , 80 , 81 , 82 , 83 , 84 , 85 , 86 , 87 , 87 , 88 , 89 , 90 , 91 , 91 , 92 , 93 , 93 , 94 , 95 , 95 , 96 , 96 , 97 , 97 , 97 , 98 , 98 , 98 , 99 , 99 , 99 , 99 , 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 99 , 99 , 99 , 99 , 98 , 98 , 98 , 97 , 97 , 97 , 96 , 96 , 95 , 95 , 94 , 93 , 93 , 92 , 91 , 91 , 90 , 89 , 88 , 87 , 87 , 86 , 85 , 84 , 83 , 82 , 81 , 80 , 79 , 78 , 77 , 75 , 74 , 73 , 72 , 71 , 69 , 68 , 67 , 66 , 64 , 63 , 62 , 60 , 59 , 57 , 56 , 54 , 53 , 52 , 50 , 48 , 47 , 45 , 44 , 42 , 41 , 39 , 37 , 36 , 34 , 33 , 31 , 29 , 28 , 26 , 24 , 22 , 21 , 19 , 17 , 16 , 14 , 12 , 10 , 9 , 7 , 5 , 3 , 2 , 0 ,
};
volatile uint8_t pwm1_index=0;
volatile uint8_t pwm2_index=0;
volatile uint8_t pwm3_index=0;
volatile uint8_t pwm4_index=0;
volatile uint8_t count;
void TIM8_UP_TIM13_IRQHandler(void)
{
/* USER CODE BEGIN TIM8_UP_TIM13_IRQn 0 */
if (__HAL_TIM_GET_IT_SOURCE(&htim8, TIM_IT_UPDATE) != RESET)
{
//8拍 A-AB-B-BC-C-CD-D-DA
if(count%60==0)
{
//pwm_index=0;
count=0;
if(pwm_count>7){pwm_count=0;pwm1_index=0;}
if(pwm_count==1){TIM8->CCER=0x2223; }
if(pwm_count==2){TIM8->CCER=0x2233; pwm2_index=0;}
if(pwm_count==3){TIM8->CCER=0x2232; }
if(pwm_count==4){TIM8->CCER=0x2332; pwm3_index=0;}
if(pwm_count==5){TIM8->CCER=0x2322;}
if(pwm_count==6){TIM8->CCER=0x3322; pwm4_index=0;}
if(pwm_count==7){TIM8->CCER=0x3222;}
if(pwm_count==0){TIM8->CCER=0x3223; pwm1_index=0;}
pwm_count++;
}
TIM8->CCR1 = 100-indexWave1[pwm1_index++];
TIM8->CCR2 = 100-indexWave1[pwm2_index++];
TIM8->CCR3 = 100-indexWave1[pwm3_index++];
TIM8->CCR4 = 100-indexWave1[pwm4_index++];
count++;
/* USER CODE END TIM8_UP_TIM13_IRQn 0 */
HAL_TIM_IRQHandler(&htim8);
/* USER CODE BEGIN TIM8_UP_TIM13_IRQn 1 */
/* USER CODE END TIM8_UP_TIM13_IRQn 1 */
}
/* USER CODE END 1 */
main函数
int main(void)
{
/* 复位所有外设,初始化Flash接口和系统滴答定时器 */
HAL_Init();
/* 配置系统时钟 */
SystemClock_Config();
MX_TIM8_Init();
/* 板载LED初始化 */
LED_GPIO_Init();
HAL_TIM_PWM_Start(&htim8,TIM_CHANNEL_1);//开启PWM通道1
HAL_TIM_PWM_Start(&htim8,TIM_CHANNEL_2);//开启PWM通道2
HAL_TIM_PWM_Start(&htim8,TIM_CHANNEL_3);//开启PWM通道3
HAL_TIM_PWM_Start(&htim8,TIM_CHANNEL_4);//开启PWM通道4
/* 在中断模式下启动定时器 */
HAL_TIM_Base_Start_IT(&htim8);
/* 无限循环 */
while (1)
{
}
}
运行效果非常安静,手指触摸电机可以感觉到轻微震动
单片机管脚实际输出波形
注意:当八拍频率过快时,28BYJ-48将会卡死