STM32 Library for DRV8825 Stepper Motor Controller IC
Please read Liability Disclaimer and License Agreement CAREFULLY
Before going further please read DRV8825 datasheet
In stepper.h add dthe following code
#ifndef __stepper_H
#define __stepper_H
#ifdef __cplusplus
extern "C" {
#endif
#include "gpio.h"
//MODE2 MODE1 MODE0 STEP MODE
//0 0 0 Full step (2-phase excitation) with 71% current
//0 0 1 1/2 step (1-2 phase excitation)
//0 1 0 1/4 step (W1-2 phase excitation)
//0 1 1 8 microsteps/step
//1 0 0 16 microsteps/step
//1 0 1 32 microsteps/step
//1 1 0 32 microsteps/step
//1 1 1 32 microsteps/step
// Below values are valid for stepper 1 connections to DRV8825
//M0 connected to PA1
//M1 connected to PA0
//M2 connected to PC3
// Below values are valid for stepper 2 connections to DRV8825
//M0 connected to PC7
//M1 connected to PC6
//M2 connected to PC12
#define STEPPERS_COUNT 2
#define GearRatio 405.0
#define AccRatio 0.2
#define MaxSpeedEnd 0.8
#define MaxStepAngle 0.9
#define STEPS_TO_BREAK 900
//Maximum steps per second
//for simple calculation keep it as multiple of 50 -> 50*36=1800steps/sec for microstepping of 1
//#define MAX_SPS1 (36 * SPS_Update)
//#define MAX_SPS2 (2 * MAX_SPS1)
//#define MAX_SPS4 (4 * MAX_SPS1)
//#define MAX_SPS8 (8 * MAX_SPS1)
//#define MAX_SPS16 (16 * MAX_SPS1)
//#define MAX_SPS32 (32 * MAX_SPS1)
extern volatile uint8_t Stepper_Fault[2];
extern volatile uint32_t Stepper_Pos[2];
typedef enum {
SS_STOPPED = 0,
SS_STARTING = 1,
SS_FULLSPEED = 2,
SS_BREAKING = 3,
SS_BREAKCORRECTION = 4
} stepper_status;
typedef struct {
uint8_t Id;
stepper_status Status;
volatile uint8_t Fault; //handle by interrupt
volatile int32_t CrtPos; //handle by interrupt
uint8_t Direction;
uint8_t Gear;
uint16_t SPS;//Steps per second. For uStep of 32 we have max. 57600SPS
uint32_t StepsDec;//When To start decelerating
uint32_t StepsToTarget;//Steps to target
} stepper_params;
void enableMotor(uint8_t motorNumber, uint8_t isOnOff);
void setGear(uint8_t motorNumber, uint8_t gear);
void directionMotor(uint8_t motorNumber, uint8_t dir);
void resetMotor(uint8_t motorNumber, uint8_t rstOnOff);
void setMotorSpeed(uint8_t motorNumber, uint16_t freq);
void Stepper_UpdateAll(void);
void Stepper_FaultUpdate(uint8_t myStepper, uint8_t value);
void Stepper_PulseTimerUpdate(uint8_t myStepper);
void Stepper_Refresh(stepper_params * crtStepper);
void Steppers_Init(void);
void Stepper_Move(uint8_t myStepper, double targetPos);
#ifdef __cplusplus
}
#endif
#endif /* __stepper_H */
In stepper.c add the following code
#include "stepper.h"
#include "tim.h"
//angle per step table
static stepper_params S_AZ, S_ALT;
static const uint16_t MaxSPS[7] = {0, 1800, 3600, 7200, 14400, 28800, 57600};
//static const double Angle[7] = {0.0, 0.9, 45, 0.225, 0.1125, 0.05625, 0.028125};
//how many steps we add every milisecond (timer 14 tick) depending on the gear selected
static const uint8_t StepIncrement[7] = {0, 2, 4, 8, 16, 32, 64};
//Timer 2 Channel 3 is controlling the Azimuth/RA/Horizontal motor, or motor 0
//Timer 5 Channel 4 is controlling the Altitude/DEC/Vertical motor, or motor 1
void enableMotor(uint8_t motorNumber, uint8_t isOnOff){
switch(motorNumber){
case 0:
if(isOnOff){
Stepper1_On;}
else{
Stepper1_Off;}
break;
case 1:
if(isOnOff){
Stepper2_On;}
else{
Stepper2_Off;}
break;
}
}
void setGear(uint8_t motorNumber, uint8_t gear){
switch(motorNumber){
case 0:
switch(gear){
case 0:
enableMotor(0, 0);
break;
case 1:
Stepper1_M0_Off;
Stepper1_M1_Off;
Stepper1_M2_Off;
break;
case 2:
Stepper1_M0_On;
Stepper1_M1_Off;
Stepper1_M2_Off;
break;
case 4:
Stepper1_M0_Off;
Stepper1_M1_On;
Stepper1_M2_Off;
break;
case 8:
Stepper1_M0_On;
Stepper1_M1_On;
Stepper1_M2_Off;
break;
case 16:
Stepper1_M0_Off;
Stepper1_M1_Off;
Stepper1_M2_On;
break;
case 32:
Stepper1_M0_On;
Stepper1_M1_Off;
Stepper1_M2_On;
break;
}
break;
case 1:
switch(gear){
case 0:
enableMotor(1, 0);
break;
case 1:
Stepper2_M0_Off;
Stepper2_M1_Off;
Stepper2_M2_Off;
break;
case 2:
Stepper2_M0_On;
Stepper2_M1_Off;
Stepper2_M2_Off;
break;
case 4:
Stepper2_M0_Off;
Stepper2_M1_On;
Stepper2_M2_Off;
break;
case 8:
Stepper2_M0_On;
Stepper2_M1_On;
Stepper2_M2_Off;
break;
case 16:
Stepper2_M0_Off;
Stepper2_M1_Off;
Stepper2_M2_On;
break;
case 32:
Stepper2_M0_On;
Stepper2_M1_Off;
Stepper2_M2_On;
break;
}
break;
}
}
void directionMotor(uint8_t motorNumber, uint8_t dir){
switch(motorNumber){
case 0:
if(dir){
Stepper1_DirA;}
else{
Stepper1_DirB;}
break;
case 1:
if(dir){
Stepper2_DirA;}
else{
Stepper2_DirB;}
break;
}
}
void resetMotor(uint8_t motorNumber, uint8_t rstOnOff){
switch(motorNumber){
case 0:
if(rstOnOff){
Stepper1_RST_On;}
else{
Stepper1_RST_Off;}
break;
case 1:
if(rstOnOff){
Stepper2_RST_On;}
else{
Stepper2_RST_Off;}
break;
}
}
void setMotorSpeed(uint8_t motorNumber, uint16_t freq){
uint32_t NewTimPeriod = ((TimTickFreq/freq) - 1);
switch(motorNumber){
case 0:
htim2.Instance->ARR = NewTimPeriod;
htim2.Instance->CNT = 0;
break;
case 1:
htim5.Instance->ARR = NewTimPeriod;
htim5.Instance->CNT = 0;
break;
}
}
static stepper_params * GetStepper(uint8_t idx) {
if(idx)
return &S_ALT;
else
return &S_AZ;
}
static void IncrementSPS(stepper_params * Stepper){
if (Stepper->SPS < MaxSPS[Stepper->Gear]) {
Stepper->SPS +=StepIncrement[Stepper->Gear];
setMotorSpeed(Stepper->Id, Stepper->SPS);
} else {
Stepper->Status = SS_FULLSPEED;
}
}
static void DecrementSPS(stepper_params * Stepper){
Stepper->SPS -=StepIncrement[Stepper->Gear];
//we have roll-over
if (Stepper->SPS > MaxSPS[Stepper->Gear]){
Stepper->SPS = 1;
}
setMotorSpeed(Stepper->Id, Stepper->SPS);
}
void Stepper_UpdateAll(void){
for(uint8_t i = 0; i < STEPPERS_COUNT; i++) {
Stepper_Refresh(GetStepper(i));
}
}
void Stepper_FaultUpdate(uint8_t myStepper, uint8_t value) {
stepper_params * CrtStepper = GetStepper(myStepper);
CrtStepper->Fault = value;
}
void Stepper_PulseTimerUpdate(uint8_t myStepper) {
stepper_params * CrtStepper = GetStepper(myStepper);
//stepper_status CrtStatus = CrtStepper->Status;
switch (CrtStepper->Status){
case SS_STOPPED:
return;
case SS_STARTING:
CrtStepper->CrtPos++; //increase the curent step
//the condition to exit SS_STARTING is handled in IncrementSPS function
break;
case SS_FULLSPEED: //Motor is in full speed interval
CrtStepper->CrtPos++; //increase the curent step
if (CrtStepper->CrtPos > CrtStepper->StepsDec){// start decelerate
CrtStepper->Status = SS_BREAKING;
}
break;
case SS_BREAKING: //Motor is in deceleration interval
CrtStepper->CrtPos++; //increase the curent step
if(CrtStepper->CrtPos == CrtStepper->StepsToTarget){
CrtStepper->Status = SS_STOPPED;
enableMotor(CrtStepper->Id, 0);//stop the motor
} else if(CrtStepper->CrtPos > CrtStepper->StepsToTarget){
//Motor exceeded the limit
CrtStepper->Status = SS_BREAKCORRECTION;
CrtStepper->SPS = 64;
setMotorSpeed(CrtStepper->Id, CrtStepper->SPS);
}
break;
case SS_BREAKCORRECTION: //Motor is correcting the position
if (CrtStepper->CrtPos > CrtStepper->StepsToTarget){
CrtStepper->CrtPos--;
} else {
CrtStepper->Status = SS_STOPPED;
enableMotor(CrtStepper->Id, 0);//stop the motor
}
break;
}
}
//this one is called once every 1ms
void Stepper_Refresh(stepper_params * crtStepper) {
switch (crtStepper->Status){
case SS_STARTING:
IncrementSPS(crtStepper);
break;
case SS_BREAKING:
DecrementSPS(crtStepper);
break;
}
}
void Steppers_Init(void) {
//init the structures
for(uint32_t i = 0; i < 2; i++) {
stepper_params * crtStepper = GetStepper(i);
crtStepper->Id = i;
crtStepper->Status = SS_STOPPED;
crtStepper->Fault = 0; //handle by interrupt
crtStepper->CrtPos = 0; //handle by interrupt
crtStepper->Direction = 1;
crtStepper->Gear = 16;
crtStepper->SPS = 57600;//Steps per second (actual frequency of the timer) this is why 32 bit timer is nice
crtStepper->StepsDec = 2;//When To start decelerating
crtStepper->StepsToTarget = 0;//Steps to target
resetMotor(i, 0);
setGear(i, crtStepper->Gear);
}
__HAL_TIM_ENABLE_IT(&htim2, TIM_IT_UPDATE);
__HAL_TIM_ENABLE_IT(&htim5, TIM_IT_UPDATE);
//Motor 0 PWM
//HAL_TIM_Base_Start(&htim2);
HAL_TIM_PWM_Start(&htim2, TIM_CHANNEL_3);
//Motor 1 PWM
//HAL_TIM_Base_Start(&htim5);
HAL_TIM_PWM_Start(&htim5, TIM_CHANNEL_4);
}
//how much we have to move the output shaft. This takes in to accout the gear ratio
void Stepper_Move(uint8_t myStepper, double targetPos) {
stepper_params * crtStepper = GetStepper(myStepper);
//if we try move the motor while motor is doing something else
if(crtStepper->Status)
return;
//the acceleration/deceleration is 20% + 20% of the total time. 60% we move at full speed
crtStepper->StepsToTarget = (((targetPos * GearRatio) / (MaxStepAngle/(double)crtStepper->Gear)) + 0.5);//here we get the rounded steps to target
//printf("S2T %d\r\n", crtStepper->StepsToTarget);
crtStepper->StepsDec = crtStepper->StepsToTarget - STEPS_TO_BREAK;
//printf("DEC %d\r\n", crtStepper->StepsDec);
setMotorSpeed(myStepper, crtStepper->SPS);
crtStepper->CrtPos = 0;
crtStepper->Status = SS_STARTING;
enableMotor(myStepper, 1);
}
Comments powered by CComment