附上:点击参考
购买元器件附带3D封装:https://weidian.com/?userid=1238350417&wfr=c&ifr=shopdetail
看到网上有好多做微型激光雕刻机的DIY,手头正好有几个拆下来的笔记本光驱,把光驱里的步进电机拆了出来,做了这个雕刻机。由于我手头没有激光头,偷懒用圆珠笔来代替激光头。
采用STM32F103ZET6最小系统板做的三轴联动,步进电机驱动没有采用专门的驱动板,使用了L298N或者L9110S,由STM32的PWM来控制步进电机。我G代码下载使用的是G-CODE SENDER来下载到开发板,还没有做SD卡脱机。
MSOS任务的参数数量在OS.H 中定义
#define TaskSum 4 任务总数。现在定义了4个,如果超过4个就必须修改,最大支持8个任务,包括GUI的任务这是TIM的初始化程序
u16 psc = 49;
TIMx_Init(TIM2,1023,psc);
//定时时间为72MHz/50/1024=1.4KHz
TIM3_PWM_Init(1023,psc);
//使用TIM3-5做PWM单独输出,TIM3 A相;TIM4 B相;TIM5 C相
TIM4_PWM_Init(1023,psc);
TIM5_PWM_Init(1023,psc);
这个是PWM对应4相的脉宽计算
#define MAICHONG 128 //每相马达的脉冲数量,总脉冲数为256个
#define MAICHONG1 MAICHONG/4 //马达的脉冲数量
#define MAICHONG2 MAICHONG/2 //马达的脉冲数量
#define MAICHONG3 MAICHONG/4*3 //马达的脉冲数量
const
u16 Sin[]={
//128个脉冲的时序,用正弦波函数发生器产生的,自己懒得去减0x3FF,在计算每相脉冲时自动计算
0x3FF,0x431,0x463,0x495,0x4C7,0x4F8,0x528,0x558,0x587,0x5B5,0x5E1,0x60D,0x638,0x661,0x688,0x6AE
,0x6D3,0x6F5,0x716,0x735,0x752,0x76D,0x786,0x79C,0x7B1,0x7C3,0x7D2,0x7E0,0x7EB,0x7F3,0x7FA,0x7FD
,0x7FE,0x7FD,0x7FA,0x7F3,0x7EB,0x7E0,0x7D2,0x7C3,0x7B1,0x79C,0x786,0x76D,0x752,0x735,0x716,0x6F5
,0x6D3,0x6AE,0x688,0x661,0x638,0x60D,0x5E1,0x5B5,0x587,0x558,0x528,0x4F8,0x4C7,0x495,0x463,0x431
};
u16 Moto_A1[MAICHONG];
u16 Moto_A2[MAICHONG];
u16 Moto_B1[MAICHONG];
u16 Moto_B2[MAICHONG];
/********************************************
函数:JiSuan
功能:计算马达4个控制端的正弦波查表数据
参数:无
返回:无
说明:
********************************************/
void
JiSuan(
void
)
{
u8 i;
for
(i=0;i<100;i++)
{
if
(i
{
Moto_A1[i] = Sin[i]-0x3ff;
Moto_A2[i] = 0;
Moto_B1[i] = 0;
Moto_B2[i] = Sin[i+MAICHONG1]-0x3ff;
}
else
if
(i
{
Moto_A1[i] = Sin[i]-0x3ff;
Moto_A2[i] = 0;
Moto_B1[i] = Sin[i-MAICHONG1]-0x3ff;
Moto_B2[i] = 0;
}
else
if
(i
{
Moto_A1[i] = 0;
Moto_A2[i] = Sin[i-MAICHONG2]-0x3ff;
Moto_B1[i] = Sin[i-MAICHONG1]-0x3ff;
Moto_B2[i] = 0;
}
else
if
(i
{
Moto_A1[i] = 0;
Moto_A2[i] = Sin[i-MAICHONG2]-0x3ff;
Moto_B1[i] = 0;
Moto_B2[i] = Sin[i-MAICHONG3]-0x3ff;
}
}
}
这个是步进电机数据的结构体
typedef
struct
{
u8 Flag;
//需要脉冲输出标志
u8 Dir;
//步进电机方向
u32 Step;
//步进电机需要的脉冲数量
s32 Current;
//步进电机当前位置
s32 Target;
//步进电机目标位置
}MOTO_Struct;
具体的步进电机控制在TIM2中断中实现,具体的函数如下
void
TIM2_IRQHandler(
void
)
//定时器中断函数
{
u16 t;
//当前脉冲位置的临时变量
if
(TIM_GetITStatus(TIM2,TIM_IT_Update)!=RESET)
//判断是否定时中断
{
if
(Moto_X.Flag)
{
if
(Moto_X.Step > 0)
{
Moto_X.Step--;
if
(Moto_X.Dir)
{
Moto_X.Current++;
}
else
{
Moto_X.Current--;
}
t= Moto_X.Current%MAICHONG;
TIM_SetCompare1(TIM4,Moto_A1[t]);
//改变PWM占空比
TIM_SetCompare2(TIM4,Moto_A2[t]);
//改变PWM占空比
TIM_SetCompare3(TIM4,Moto_B1[t]);
//改变PWM占空比
TIM_SetCompare4(TIM4,Moto_B2[t]);
//改变PWM占空比
}
else
{
Moto_X.Flag = 0;
TIM_SetCompare1(TIM4,0);
//改变PWM占空比
TIM_SetCompare2(TIM4,0);
//改变PWM占空比
TIM_SetCompare3(TIM4,0);
//改变PWM占空比
TIM_SetCompare4(TIM4,0);
//改变PWM占空比
}
}
if
(Moto_Y.Flag)
{
if
(Moto_Y.Step > 0)
{
Moto_Y.Step--;
if
(Moto_Y.Dir)
{
Moto_Y.Current++;
}
else
{
Moto_Y.Current--;
}
t= Moto_Y.Current%MAICHONG;
TIM_SetCompare1(TIM3,Moto_A1[t]);
//改变PWM占空比
TIM_SetCompare2(TIM3,Moto_A2[t]);
//改变PWM占空比
TIM_SetCompare3(TIM3,Moto_B1[t]);
//改变PWM占空比
TIM_SetCompare4(TIM3,Moto_B2[t]);
//改变PWM占空比
}
else
{
Moto_Y.Flag = 0;
TIM_SetCompare1(TIM3,0);
//改变PWM占空比
TIM_SetCompare2(TIM3,0);
//改变PWM占空比
TIM_SetCompare3(TIM3,0);
//改变PWM占空比
TIM_SetCompare4(TIM3,0);
//改变PWM占空比
}
}
if
(Moto_Z.Flag)
{
if
(Moto_Z.Step > 0)
{
Moto_Z.Step--;
if
(Moto_Z.Dir)
{
Moto_Z.Current++;
}
else
{
Moto_Z.Current--;
}
t= Moto_Z.Current%MAICHONG;
TIM_SetCompare1(TIM5,Moto_A1[t]);
//改变PWM占空比
TIM_SetCompare2(TIM5,Moto_A2[t]);
//改变PWM占空比
TIM_SetCompare3(TIM5,Moto_B1[t]);
//改变PWM占空比
TIM_SetCompare4(TIM5,Moto_B2[t]);
//改变PWM占空比
}
else
{
Moto_Z.Flag = 0;
TIM_SetCompare1(TIM5,0);
//改变PWM占空比
TIM_SetCompare2(TIM5,0);
//改变PWM占空比
TIM_SetCompare3(TIM5,0);
//改变PWM占空比
TIM_SetCompare4(TIM5,0);
//改变PWM占空比
}
}
}
TIM_ClearITPendingBit(TIM2, TIM_FLAG_Update);
//必须清除中断标志位否则一直中断
}