Skip to content

Commit

Permalink
Formatting
Browse files Browse the repository at this point in the history
Readme
  • Loading branch information
Denis Voltmann committed Oct 31, 2022
1 parent 9e6f9ae commit 600848a
Show file tree
Hide file tree
Showing 4 changed files with 212 additions and 147 deletions.
92 changes: 50 additions & 42 deletions DendoStepper.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -73,13 +73,13 @@ void DendoStepper::init()
.intr_type = TIMER_INTR_LEVEL, // interrupt
.counter_dir = TIMER_COUNT_UP, // count up duh
.auto_reload = TIMER_AUTORELOAD_EN, // reload pls
.divider = 80000000ULL/TIMER_F, // ns resolution
.divider = 80000000ULL / TIMER_F, // ns resolution
};

//calculate stepsPerRot
ctrl.stepsPerRot = (360.0/conf.stepAngle)*conf.miStep;
// calculate stepsPerRot
ctrl.stepsPerRot = (360.0 / conf.stepAngle) * conf.miStep;

STEP_LOGI("DendoStepper","Steps per one rotation:%d",ctrl.stepsPerRot);
STEP_LOGI("DendoStepper", "Steps per one rotation:%d", ctrl.stepsPerRot);

if (conf.timer_group != TIMER_GROUP_MAX && conf.timer_idx != TIMER_MAX)
{
Expand Down Expand Up @@ -127,20 +127,22 @@ esp_err_t DendoStepper::runPos(int32_t relative)
if (ctrl.status == DISABLED) // if motor is disabled, enable it
enableMotor();
ctrl.status = ACC;
setDir(relative < 0); // set CCW if <0, else set CW
setDir(relative < 0); // set CCW if <0, else set CW
currentPos += relative;
calc(abs(relative)); // calculate velocity profile
calc(abs(relative)); // calculate velocity profile
ESP_ERROR_CHECK(timer_set_alarm_value(conf.timer_group, conf.timer_idx, ctrl.stepInterval)); // set HW timer alarm to stepinterval
ESP_ERROR_CHECK(timer_start(conf.timer_group, conf.timer_idx)); // start the timer

return ESP_OK;
}

esp_err_t DendoStepper::runPosMm(int32_t relative){
if(ctrl.stepsPerMm == 0){
STEP_LOGE("DendoStepper","Steps per millimeter not set, cannot move!");
esp_err_t DendoStepper::runPosMm(int32_t relative)
{
if (ctrl.stepsPerMm == 0)
{
STEP_LOGE("DendoStepper", "Steps per millimeter not set, cannot move!");
}
return runPos(relative*ctrl.stepsPerMm);
return runPos(relative * ctrl.stepsPerMm);
}

esp_err_t DendoStepper::runAbs(uint32_t position)
Expand All @@ -156,19 +158,20 @@ esp_err_t DendoStepper::runAbs(uint32_t position)
if (position == currentPos) // we cant go anywhere
return 0;


int32_t relativeSteps = 0;
relativeSteps = (int32_t)position - currentPos;

ESP_LOGI("DendoStepper","Cur: %llu move %d", currentPos, relativeSteps);
ESP_LOGI("DendoStepper", "Cur: %llu move %d", currentPos, relativeSteps);
return runPos(relativeSteps); // run to new position
}

esp_err_t DendoStepper::runAbsMm(uint32_t position){
if(ctrl.stepsPerMm == 0){
STEP_LOGE("DendoStepper","Steps per millimeter not set, cannot move!");
esp_err_t DendoStepper::runAbsMm(uint32_t position)
{
if (ctrl.stepsPerMm == 0)
{
STEP_LOGE("DendoStepper", "Steps per millimeter not set, cannot move!");
}
return runAbs(position*ctrl.stepsPerMm);
return runAbs(position * ctrl.stepsPerMm);
}

void DendoStepper::setSpeed(uint32_t speed, uint16_t accT, uint16_t decT)
Expand All @@ -181,21 +184,24 @@ void DendoStepper::setSpeed(uint32_t speed, uint16_t accT, uint16_t decT)

void DendoStepper::setSpeedMm(uint32_t speed, uint16_t accT, uint16_t decT)
{
if(ctrl.stepsPerMm == 0){
STEP_LOGE("DendoStepper","Steps per millimeter not set, cannot set the speed!");
if (ctrl.stepsPerMm == 0)
{
STEP_LOGE("DendoStepper", "Steps per millimeter not set, cannot set the speed!");
}
ctrl.speed = speed*ctrl.stepsPerMm;
ctrl.speed = speed * ctrl.stepsPerMm;

ctrl.acc = ctrl.speed / (accT / 4000.0);
ctrl.dec = ctrl.speed / (decT / 4000.0);
STEP_LOGI("DendoStepper", "Speed set: v=%d mm/s t+=%d s t-=%d s", speed, accT, decT);
}

void DendoStepper::setStepsPerMm(uint16_t steps){
void DendoStepper::setStepsPerMm(uint16_t steps)
{
ctrl.stepsPerMm = steps;
}

uint16_t DendoStepper::getStepsPerMm(){
uint16_t DendoStepper::getStepsPerMm()
{
return ctrl.stepsPerMm;
}

Expand All @@ -209,8 +215,9 @@ uint64_t DendoStepper::getPosition()
return currentPos;
}

uint64_t DendoStepper::getPositionMm(){
return getPosition()/ctrl.stepsPerMm;
uint64_t DendoStepper::getPositionMm()
{
return getPosition() / ctrl.stepsPerMm;
}

void DendoStepper::resetAbsolute()
Expand All @@ -220,33 +227,36 @@ void DendoStepper::resetAbsolute()

void DendoStepper::runInf(bool direction)
{
if(ctrl.status > IDLE){
STEP_LOGE("DendoStepper","Motor is moving, this command will be ignored");
if (ctrl.status > IDLE)
{
STEP_LOGE("DendoStepper", "Motor is moving, this command will be ignored");
return;
}
if(ctrl.status == DISABLED){
if (ctrl.status == DISABLED)
{
enableMotor();
}
ctrl.runInfinite = true;
setDir(direction);
calc(UINT32_MAX);
ESP_ERROR_CHECK(timer_set_alarm_value(conf.timer_group, conf.timer_idx, ctrl.stepInterval)); // set HW timer alarm to stepinterval
ESP_ERROR_CHECK(timer_start(conf.timer_group, conf.timer_idx)); // start the timer
ESP_ERROR_CHECK(timer_start(conf.timer_group, conf.timer_idx)); // start the timer
}

uint16_t DendoStepper::getSpeed()
{
return ctrl.speed;
}

uint16_t DendoStepper::getAcc()
float DendoStepper::getAcc()
{
return ctrl.acc;
}

void DendoStepper::stop()
{
if(ctrl.status <= IDLE){
if (ctrl.status <= IDLE)
{
return;
}
ctrl.runInfinite = false;
Expand Down Expand Up @@ -275,7 +285,6 @@ bool DendoStepper::xISR()
GPIO.out_w1ts = (1ULL << conf.stepPin);
// add and substract one step


ctrl.stepCnt++;

// we are done
Expand Down Expand Up @@ -303,7 +312,7 @@ bool DendoStepper::xISR()
ctrl.status = COAST; // we are coasting
}

ctrl.stepInterval = TIMER_F/ctrl.currentSpeed;
ctrl.stepInterval = TIMER_F / ctrl.currentSpeed;
// set alarm to calculated interval and disable pin
GPIO.out_w1tc = (1ULL << conf.stepPin);
timer_set_alarm_value(conf.timer_group, conf.timer_idx, ctrl.stepInterval);
Expand All @@ -312,32 +321,31 @@ bool DendoStepper::xISR()

void DendoStepper::calc(uint32_t targetSteps)
{

ctrl.accSteps = 0.5*ctrl.acc*(ctrl.speed/ctrl.acc)*(ctrl.speed/ctrl.acc);

ctrl.decSteps = 0.5*ctrl.dec*(ctrl.speed/ctrl.dec)*(ctrl.speed/ctrl.dec);
ctrl.accSteps = 0.5 * ctrl.acc * (ctrl.speed / ctrl.acc) * (ctrl.speed / ctrl.acc);

ctrl.decSteps = 0.5 * ctrl.dec * (ctrl.speed / ctrl.dec) * (ctrl.speed / ctrl.dec);

if (targetSteps < (ctrl.decSteps + ctrl.accSteps))
{
ESP_LOGI("Dendostepper","Computing new speed");
ESP_LOGI("Dendostepper", "Computing new speed");

ctrl.speed = sqrt(2*targetSteps*((ctrl.dec*ctrl.acc)/(ctrl.dec+ctrl.acc)));
ctrl.accSteps = 0.5*ctrl.acc*(ctrl.speed/ctrl.acc)*(ctrl.speed/ctrl.acc);
ctrl.decSteps = 0.5*ctrl.dec*(ctrl.speed/ctrl.dec)*(ctrl.speed/ctrl.dec);
ctrl.speed = sqrt(2 * targetSteps * ((ctrl.dec * ctrl.acc) / (ctrl.dec + ctrl.acc)));
ctrl.accSteps = 0.5 * ctrl.acc * (ctrl.speed / ctrl.acc) * (ctrl.speed / ctrl.acc);
ctrl.decSteps = 0.5 * ctrl.dec * (ctrl.speed / ctrl.dec) * (ctrl.speed / ctrl.dec);
}

ctrl.accEnd = ctrl.accSteps;
ctrl.coastEnd = targetSteps - ctrl.decSteps;
ctrl.targetSpeed = ctrl.speed;

ctrl.accInc = ctrl.targetSpeed/(double)ctrl.accSteps;
ctrl.decInc = ctrl.targetSpeed/(double)ctrl.decSteps;
ctrl.accInc = ctrl.targetSpeed / (double)ctrl.accSteps;
ctrl.decInc = ctrl.targetSpeed / (double)ctrl.decSteps;

ctrl.currentSpeed = ctrl.accInc;

ctrl.stepInterval = TIMER_F/ctrl.currentSpeed;
ctrl.stepInterval = TIMER_F / ctrl.currentSpeed;
ctrl.stepsToGo = targetSteps;

STEP_LOGI("calc", "acc end:%u coastend:%u stepstogo:%u speed:%f acc:%f int: %u", ctrl.accEnd, ctrl.coastEnd, ctrl.stepsToGo, ctrl.speed, ctrl.acc, ctrl.stepInterval);

}
102 changes: 74 additions & 28 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,50 +1,99 @@
# DendoStepper

#### This docs are outdated, new ones will be ready soon

Work in progress, maybe unstable.
Work in progress, maybe unstable. Opening issues is more than welcome.
This library takes care of pulse generating for stepper motor drivers with STEP/DIR interface. Pulse generating utilizes general purpose timers to achieve some usable accuracy and smoothness.
Currently supports only linear acceleration and deceleration, exponential profile is TBD.
Currently supports only linear acceleration and deceleration.

### Known limitations
- maximum number of controlled stepper motors is 4, this is limited by number of general purpose timers
- If the motor is moving, it is not possible to move it to another direction.

## Usage

```c++
typedef struct
{
uint8_t step_p; //step signal gpio
uint8_t dir_p; //dir signal gpio
uint8_t en_p; //enable signal gpio
timer_group_t timer_group; //timer group, useful if we are controlling more than 2 steppers
timer_idx_t timer_idx; //timer index, useful if we are controlling 2steppers
uint8_t stepPin; /** step signal pin */
uint8_t dirPin; /** dir signal pin */
uint8_t enPin; /** enable signal pin */
timer_group_t timer_group; /** timer group, useful if we are controlling more than 2 steppers */
timer_idx_t timer_idx; /** timer index, useful if we are controlling 2steppers */
microStepping_t miStep; /** microstepping configured on driver - used in distance calculation */
float stepAngle; /** one step angle in degrees (usually 1.8deg), used in steps per rotation calculation */
} DendoStepper_config_t;

DendoStepper(DendoStepper_config_t*);
enum microStepping_t
{
MICROSTEP_1 = 0x1,
MICROSTEP_2,
MICROSTEP_4 = 0x4,
MICROSTEP_8 = 0x8,
MICROSTEP_16 = 0x10,
MICROSTEP_32 = 0x20,
MICROSTEP_64 = 0x40,
MICROSTEP_128 = 0x80,
MICROSTEP_256 = 0x100,
};

```
Constructor - accepts DendoStepper_config_t struct as parameter. This struct needs to be initialized before calling constructor.
timer_group and timer_idx are used to assign different timers to different instances.
Configuration struct, can be allocated on stack or heap.

```c++
void init();
```
Initializes GPIO and Timer peripherals, registers ISR. Expects populated config struct is alreay passed to the object
Initializes GPIO and Timer peripherals, registers ISR. Expects populated config struct is alreay passed to the class using config()

```c++
void config(DendoStepper_config_t* config);
```
Configures the class as per passed config struct pointer.
```c++
void config(const DendoStepper_config_t* config);
void setStepsPerMm(uint16_t steps);
uint16_t getStepsPerMm();
```
Same as init, but you can pass populated config struct if you didn't pass it in constructor.
Sets or gets steps needed to move one millimiter, useful if stepper is moving along linear axis.

```c++
void setSpeed(uint16_t speed,uint16_t accTimeMs);
void setSpeed(uint16_t speed,uint16_t accT, uint16_t decT);
uint16_t getSpeed();
float getAcc();
```
Sets maximum speed in steps per second, acceleration and deceleration time in milliseconds.
Gets speed in steps per second
Gets acceleration in steps per second per second
```c++
void setSpeedMm(uint16_t speed,uint16_t accT, uint16_t decT);
```
Sets maximum speed in steps per second and acceleration time in milliseconds.
Sets maximum speed in mm/s, acceleration and deceleration time in milliseconds. Expects already defined steps per millimeter with setStepsPerMm()

```c++
void runPos(int32_t relative);
```
Runs motor to position relative from current position, respecting constraints set with setSpeed()
Runs motor to position relative from current position in steps, respecting constraints set with setSpeed()
```c++
void runPosMm(int32_t relative);
```
Runs motor to position relative from current position in millimeters, respecting constraints set with setSpeed()
Expects already defined steps per millimeter with setStepsPerMm()

```c++
bool runAbsolute(uint32_t position);
```
Runs motor in absolute coordinate plane. Unit: steps (should be constrained with home switch)
```c++
bool runAbsoluteMm(uint32_t position);
```
Runs motor in absolute coordinate plane. Unit: millimiters (should be constrained with home switch)
Expects already defined steps per millimeter with setStepsPerMm()

```c++
bool runInf(bool direction);
```
Runs motor infintely in desired direction with constrains set using setSpeed().
```c++
void disableMotor();
Expand All @@ -65,29 +114,26 @@ enum motor_status{
```
Returns current state of motor, return type is enum motor_status

```c++
bool runAbsolute(uint32_t position);
```
Runs motor in absolute coordinate plane(should be constrained with home switch)

```c++
void resetAbsolute();
```
Resets absolute position to 0. Called for ex. when endswitch is hit.
Resets absolute position to 0. Called for ex. when endswitch is hit.

```c++
uint16_t getSpeed();
void getPosition();
```
Returns currently set motor speed
Gets current position in absolute coordinate plane in steps.

```c++
uint16_t getAcc();
void getPositionMm();
```
Returns currently set acceleration time in ms
Gets current position in absolute coordinate plane in millimeters.
Expects already defined steps per millimeter with setStepsPerMm()

```c++
void stop();
```
Stops the motor dead on the spot. Eg. e-stop.
Stops the motor dead on the spot. No deceleration is performed this way. Eg. e-stop.


Loading

0 comments on commit 600848a

Please sign in to comment.