步进电机使用总结
1、步进电机励磁顺序
2、驱动电路
3、步进电机驱动芯片
UPA1759G 为NMOS。
4、需要注意的几点:
1) 我们使用的步进电机 800pps为最佳。
2) 使用定时器定时880pps即1250us执行一拍
3) 步进电机为共阳极,驱动器为NMOS的UPA1759G。软件处理时需要反向驱动处理
4) 步进电机的执行一次尽量整步(8拍的倍数)执行
5) 步进电机正反向转动时,不应清除当前8拍计数值,而是进行正向加,反向减。
5、步进电机驱动程序
/**********************************************************************
* step_motor.c
* 步进电机执行模块
* 模块功能:按照调用执行相应步进电机的相应步数
* 保存各个步进电机当前的状态(当前所走步数、是否达到目标位置)
*********************************************************************/
#include
#include
#include
/**********需要修改的部分 start******************************************************/
// 步进电机旋转方向
#define VALVE_ONE_MOTOR_POS_AS_CLOCK_WISE 1
#define VALVE_TWO_MOTOR_POS_AS_CLOCK_WISE 0
#define NOZZLE_MOTOR_POS_AS_CLOCK_WISE 0
#define HIGH 1 // 表示高低电平
#define LOW 0
/**********需要修改的部分 end******************************************************/
#define MOTOR_INTERVAL_US 1250 // 1300 //500 // 370 // 700 // 1300 // 步进电机每步间隔时间 64us的整数倍1280us
/* 步进电机时序 */
static const uint8 _pos_mode[8] ={0x09,0x08,0x0c,0x04,0x06,0x02,0x03,0x01}; // positive eightbeat
static const uint8 _neg_mode[8] ={0x01,0x03,0x02,0x06,0x04,0x0C,0x08,0x09}; // negative eightbeat
#if(VALVE_ONE_MOTOR_POS_AS_CLOCK_WISE == 1)
static const uint8 *valve_one_motor_pos= _pos_mode;
#else
static const uint8 *valve_one_motor_pos= _neg_mode;
#endif
#if(VALVE_TWO_MOTOR_POS_AS_CLOCK_WISE == 1)
static const uint8 *valve_two_motor_pos= _pos_mode;
#else
static const uint8 *valve_two_motor_pos= _neg_mode;
#endif
#if(NOZZLE_MOTOR_POS_AS_CLOCK_WISE == 1)
static const uint8 *nozzle_motor_pos = _pos_mode;
#else
static const uint8 *nozzle_motor_pos = _neg_mode;
#endif
/*******************************************************************************************/
//让外部检测步进电机是否已经达到目标位置
struct _motors_ok
{
unsignedvalve_one_motor_ok: 1;
unsignedvalve_two_motor_ok: 1;
unsignednozzle_motor_ok: 1;
};
static struct _motors_ok motors = {
1,
1,
1,
};
uint8 is_valve_one_motor_ok(void)
{
returnmotors.valve_one_motor_ok;
}
uint8 is_valve_two_motor_ok(void)
{
returnmotors.valve_two_motor_ok;
}
uint8 is_nozzle_motor_ok(void)
{
returnmotors.nozzle_motor_ok;
}
static void waiting_for_motors_ok(void)
{
overlay uint8 i = 0;
while(!motors.valve_one_motor_ok||
!motors.valve_two_motor_ok||
!motors.nozzle_motor_ok)
for(i= 0; i < 200; i++) feed_wdt();
}
/*******************************************************************************************/
/*******************************************************************************************/
// 实时记录每个步进电机的步数和拍数
static int16 valve_one_motor_current = 0;
static int16 valve_one_motor_target = 0;
static uint8 valve_one_motor_step_count = 0;
static int16 valve_two_motor_current = 0;
static int16 valve_two_motor_target = 0;
static uint8 valve_two_motor_step_count = 0;
static int16 nozzle_motor_current = 0;
static int16 nozzle_motor_target =0;
static uint8 nozzle_motor_step_count = 0;
/**************************************************************************************/
void valve_one_motor_begin(int16 target)
{
// if(target== 0) // 退回到原位, 那么需要多退回一点
// target = -100;
interrupt_disable();
valve_one_motor_target = target;
// valve_one_motor_step_count= 0;
motors.valve_one_motor_ok = 0;
if(valve_one_motor_current< 0) {
valve_one_motor_current= 0;
}
interrupt_enable();
VALVE_ONE_MOTOR_IOS_OUTPUT;
// open_timer_4(MOTOR_INTERVAL_US,1,1,1);
open_timer_4(MOTOR_INTERVAL_US,1,0,1);
}
static void valve_one_motor_ok_end(void)
{
VALVE_ONE_MOTOR_IOS_OUTPUT;
VALVE_ONE_MOTOR_1(LOW);
VALVE_ONE_MOTOR_2(LOW);
VALVE_ONE_MOTOR_3(LOW);
VALVE_ONE_MOTOR_4(LOW);
if(valve_one_motor_current< 0) {
valve_one_motor_current= 0;
valve_one_motor_target= 0;
}
motors.valve_one_motor_ok= 1;
}
/**************************************************************************************/
void valve_two_motor_begin(int16 target)
{
interrupt_disable();
valve_two_motor_target = target;
// valve_two_motor_step_count= 0;
motors.valve_two_motor_ok = 0;
if(valve_two_motor_current< 0) {
valve_two_motor_current= 0;
}
interrupt_enable();
VALVE_TWO_MOTOR_IOS_OUTPUT;
// open_timer_4(MOTOR_INTERVAL_US,1,1,1);
open_timer_4(MOTOR_INTERVAL_US,1,0,1);
}
static void valve_two_motor_ok_end(void)
{
VALVE_TWO_MOTOR_IOS_OUTPUT;
VALVE_TWO_MOTOR_4(LOW);
VALVE_TWO_MOTOR_3(LOW);
VALVE_TWO_MOTOR_2(LOW);
VALVE_TWO_MOTOR_1(LOW);
if(valve_two_motor_current< 0) {
valve_two_motor_current= 0;
valve_two_motor_target= 0;
}
motors.valve_two_motor_ok= 1;
}
/**************************************************************************************/
void nozzle_motor_begin(int16 target)
{
interrupt_disable();
nozzle_motor_target = target;
// nozzle_motor_step_count= 0;
motors.nozzle_motor_ok = 0;
if(nozzle_motor_current< 0) {
nozzle_motor_current= 0;
}
interrupt_enable();
NOZZLE_MOTOR_IOS_OUTPUT;
// open_timer_4(MOTOR_INTERVAL_US,1,1,1);
open_timer_4(MOTOR_INTERVAL_US,1,0,1);
}
static void nozzle_motor_ok_end(void)
{
NOZZLE_MOTOR_IOS_OUTPUT;
NOZZLE_MOTOR_4(LOW);
NOZZLE_MOTOR_3(LOW);
NOZZLE_MOTOR_2(LOW);
NOZZLE_MOTOR_1(LOW);
if(nozzle_motor_current< 0) {
nozzle_motor_current= 0;
nozzle_motor_target= 0;
}
motors.nozzle_motor_ok= 1;
}
uint16 nozzle_motor_position(void)
{
if(nozzle_motor_current< 0)
return0;
else
return(uint16)nozzle_motor_current;
}
/**************************************************************************************/
// 换向阀速度比喷管速度快,大约换向阀的电机每拍750us, 喷管电机每拍1100US
static union __timer{
struct {
unsignedcounter_0: 1;
unsignedcounter_1: 2;
};
uint8counter;
}timer;
// 步进电机中断函数
void step_motors_intr_func(void)
{
/* staticuint8 *rotation_mode_valve_one = 0;
staticuint8 *rotation_mode_valve_two = 0;
staticuint8 *rotation_mode_nozzle = 0;
*/
timer.counter++;
//三个换向阀 位置都到达了目标位置,停止定时器
if(valve_one_motor_target == valve_one_motor_current &&
valve_two_motor_target== valve_two_motor_current &&
nozzle_motor_target== nozzle_motor_current) {
valve_one_motor_ok_end();
valve_two_motor_ok_end();
nozzle_motor_ok_end();
close_timer_4();
}else {
// if(timer.counter_0 == 0) {
//换向阀1目标位置与当前位置不相等
if(valve_one_motor_target != valve_one_motor_current) {
// overlay uint8*rotation_mode_valve_one = (uint8 *)valve_one_motor_pos;
// rotation_mode_valve_one =(uint8 *)valve_one_motor_pos;
// interrupt_disable();
//正向转
if(valve_one_motor_target< valve_one_motor_current)
{
// rotation_mode_valve_one= (uint8 *)valve_one_motor_neg;
valve_one_motor_current--;
if(valve_one_motor_step_count> 0) {
valve_one_motor_step_count--;
} else {
valve_one_motor_step_count= 7;
}
}else {
valve_one_motor_current++;
if(valve_one_motor_step_count< 7) {
valve_one_motor_step_count++;
}else {
valve_one_motor_step_count= 0;
}
}
if(valve_one_motor_step_count < 8) {
VALVE_ONE_MOTOR_1((valve_one_motor_pos[valve_one_motor_step_count] & 0x01));
VALVE_ONE_MOTOR_2(((valve_one_motor_pos[valve_one_motor_step_count]& 0x02) >> 1));
VALVE_ONE_MOTOR_3(((valve_one_motor_pos[valve_one_motor_step_count]& 0x04) >> 2));
VALVE_ONE_MOTOR_4(((valve_one_motor_pos[valve_one_motor_step_count]& 0x08) >> 3));
}
// interrupt_enable();
}else {
valve_one_motor_ok_end();
}
// }
// if(timer.counter_0 == 0) {
//换向阀2目标位置与当前位置不相等
if(valve_two_motor_target != valve_two_motor_current) {
// rotation_mode_valve_two = (uint8*)valve_two_motor_pos;
// interrupt_disable();
//正向转
if(valve_two_motor_target< valve_two_motor_current)
{
// rotation_mode_valve_two= (uint8 *)valve_two_motor_neg;
valve_two_motor_current--;
if(valve_two_motor_step_count> 0) {
valve_two_motor_step_count--;
}else {
valve_two_motor_step_count= 7;
}
}else {
valve_two_motor_current++;
if(valve_two_motor_step_count< 7) {
valve_two_motor_step_count++;
}else {
valve_two_motor_step_count= 0;
}
}
if(valve_two_motor_step_count < 8) {
VALVE_TWO_MOTOR_1((valve_two_motor_pos[valve_two_motor_step_count] & 0x01));
VALVE_TWO_MOTOR_2(((valve_two_motor_pos[valve_two_motor_step_count]& 0x02) >> 1));
VALVE_TWO_MOTOR_3(((valve_two_motor_pos[valve_two_motor_step_count]& 0x04) >> 2));
VALVE_TWO_MOTOR_4(((valve_two_motor_pos[valve_two_motor_step_count]& 0x08) >> 3));
}
// interrupt_enable();
}else {
valve_two_motor_ok_end();
}
// }
// if(timer.counter_0 == 0) {
// if(timer.counter == 3 || timer.counter ==6) {
//喷管目标位置与当前位置不相等
if(nozzle_motor_target != nozzle_motor_current) {
// rotation_mode_nozzle = (uint8*)nozzle_motor_pos;
interrupt_disable();
//反向转
if(nozzle_motor_target
// rotation_mode_nozzle= (uint8 *)nozzle_motor_neg;
nozzle_motor_current--;
if(nozzle_motor_step_count > 0){
nozzle_motor_step_count--;
} else {
nozzle_motor_step_count =7;
}
} else {
nozzle_motor_current++;
if(nozzle_motor_step_count < 7){
nozzle_motor_step_count++;
} else {
nozzle_motor_step_count =0;
}
}
if (nozzle_motor_step_count < 8) {
NOZZLE_MOTOR_1((nozzle_motor_pos[nozzle_motor_step_count] & 0x01));
NOZZLE_MOTOR_2(((nozzle_motor_pos[nozzle_motor_step_count]& 0x02) >> 1));
NOZZLE_MOTOR_3(((nozzle_motor_pos[nozzle_motor_step_count]& 0x04) >> 2));
NOZZLE_MOTOR_4(((nozzle_motor_pos[nozzle_motor_step_count]& 0x08) >> 3));
}
interrupt_enable();
}else {
nozzle_motor_ok_end();
}
}
// }
if(timer.counter>= 6)
timer.counter= 0;
}
/**************************************************************************************/
// 初始化函数
static void step_motors_io_init(void)
{
//io init
//valve one step motor ios
VALVE_ONE_MOTOR_IOS_OUTPUT;
VALVE_ONE_MOTOR_1(LOW);
VALVE_ONE_MOTOR_2(LOW);
VALVE_ONE_MOTOR_3(LOW);
VALVE_ONE_MOTOR_4(LOW);
//valve two step motor ios
VALVE_TWO_MOTOR_IOS_OUTPUT;
VALVE_TWO_MOTOR_1(LOW);
VALVE_TWO_MOTOR_2(LOW);
VALVE_TWO_MOTOR_3(LOW);
VALVE_TWO_MOTOR_4(LOW);
//nozzle_motor step motor ios
NOZZLE_MOTOR_IOS_OUTPUT;
NOZZLE_MOTOR_1(LOW);
NOZZLE_MOTOR_2(LOW);
NOZZLE_MOTOR_3(LOW);
NOZZLE_MOTOR_4(LOW);
valve_one_motor_current = 4200;
valve_one_motor_target =4200;
valve_one_motor_step_count = 0;
valve_two_motor_current = 4200;
valve_two_motor_target =4200;
valve_two_motor_step_count = 0;
nozzle_motor_current = 0;
nozzle_motor_target =0;
nozzle_motor_step_count = 0;
}
void valve_motors_init(void)
{
overlay uint16 i =0, j = 0;
step_motors_io_init();
valve_one_motor_begin(-100);
valve_two_motor_begin(-100);
}
/*********************************************************/
// 初始化函数
void step_motors_module_init(void)
{
overlay uint16 i =0, j = 0;
step_motors_io_init_1();
//while(1){
nozzle_motor_begin(3000);
valve_one_motor_begin(4200);
valve_two_motor_begin(4200);
waiting_for_motors_ok();
//开始电磁阀进水,水泵出水
for(j= 0; j < 5; j++ )
for(i= 0; i < 30000; i++)
feed_wdt();
nozzle_motor_begin(-100);
valve_one_motor_begin(-100);
valve_two_motor_begin(-100);
waiting_for_motors_ok();
for(j=0; j < 5; j++ )
for(i= 0; i < 30000; i++)
feed_wdt();
//}
}
/**************************************************************************************/
// FILE END