Compare commits
9 Commits
stepper_cu
...
stepper
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
04d9a4e12d | ||
|
|
279ac0e07e | ||
|
|
1c59e0097b | ||
|
|
5d7c67ab9a | ||
|
|
8d2428d285 | ||
|
|
dc6deeb3d0 | ||
|
|
0a05340763 | ||
|
|
45409676a0 | ||
|
|
de42b6252e |
@@ -55,6 +55,9 @@ void DendoStepper::init(uint8_t stepP, uint8_t dirP, uint8_t enP, timer_group_t
|
||||
|
||||
void DendoStepper::init()
|
||||
{
|
||||
ESP_LOGW("DendoStepper", "semaphore init");
|
||||
semaphore_isrVariables = xSemaphoreCreateBinary();
|
||||
xSemaphoreGive(semaphore_isrVariables);
|
||||
uint64_t mask = (1ULL << conf.stepPin) | (1ULL << conf.dirPin) | (1ULL << conf.enPin); // put output gpio pins in bitmask
|
||||
gpio_config_t gpio_conf = {
|
||||
// config gpios
|
||||
@@ -114,25 +117,36 @@ timer_avail:
|
||||
ESP_ERROR_CHECK(timer_isr_callback_add(conf.timer_group, conf.timer_idx, xISRwrap, this, 0)); // add callback fn to run when alarm is triggrd
|
||||
}
|
||||
|
||||
|
||||
esp_err_t DendoStepper::runPos(int32_t relative)
|
||||
{
|
||||
if (!relative) // why would u call it with 0 wtf
|
||||
return ESP_ERR_NOT_SUPPORTED;
|
||||
if (ctrl.status > IDLE)
|
||||
{ // we are running, we need to adjust steps accordingly, for now just stop the movement
|
||||
STEP_LOGW("DendoStepper", "Finising previous move, this command will be ignored");
|
||||
return ESP_ERR_NOT_SUPPORTED;
|
||||
}
|
||||
|
||||
//TODO only enable when actually moving
|
||||
if (ctrl.status == DISABLED) // if motor is disabled, enable it
|
||||
enableMotor();
|
||||
ctrl.status = ACC;
|
||||
|
||||
setDir(relative < 0); // set CCW if <0, else set CW
|
||||
currentPos += relative;
|
||||
|
||||
if (!relative) // why would u call it with 0 wtf
|
||||
return ESP_ERR_NOT_SUPPORTED;
|
||||
|
||||
if (ctrl.status > IDLE) { //currently moving
|
||||
//ctrl.status = ctrl.status==COAST ? COAST : ACC; //stay at coast otherwise switch to ACC
|
||||
ctrl.stepsRemaining = ctrl.stepsToGo - ctrl.stepCnt;
|
||||
calc(abs(relative) + ctrl.stepsRemaining); //calculate new velolcity profile for new+remaining steps
|
||||
ESP_LOGW("DendoStepper", "EXTEND running movement (stepsRemaining: %d + stepsNew: %d - current state: %d)", ctrl.stepsRemaining, abs(relative), (int)ctrl.status);
|
||||
ESP_ERROR_CHECK(timer_set_alarm_value(conf.timer_group, conf.timer_idx, ctrl.stepInterval)); // set HW timer alarm to stepinterval
|
||||
}
|
||||
|
||||
else { //current state is IDLE
|
||||
//ctrl.statusPrev = ctrl.status; //update previous status
|
||||
calc(abs(relative)); // calculate velocity profile
|
||||
ctrl.status = ACC;
|
||||
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
|
||||
}
|
||||
|
||||
//printf("runpos end -- steps: %d, status: %d, olddir: %d, newdir: %d\n", relative, ctrl.status, ctrl.dir, newDir);
|
||||
currentPos += relative; //(target position / not actual)
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
@@ -145,26 +159,31 @@ esp_err_t DendoStepper::runPosMm(int32_t relative)
|
||||
return runPos(relative * ctrl.stepsPerMm);
|
||||
}
|
||||
|
||||
//customized: if already running and direction is the same immediately pass to runPos
|
||||
esp_err_t DendoStepper::runAbs(uint32_t position)
|
||||
{
|
||||
if (getState() > IDLE) // we are already moving, so stop it
|
||||
stop();
|
||||
while (getState() > IDLE)
|
||||
{
|
||||
// waiting for idle, watchdog should take care of inf loop if it occurs
|
||||
vTaskDelay(1);
|
||||
} // shouldnt take long tho
|
||||
|
||||
if (position == currentPos) // we cant go anywhere
|
||||
return 0;
|
||||
//exit if nothing to do
|
||||
if (position == currentPos) return 0; //already at position
|
||||
|
||||
//calculate steps necessary
|
||||
int32_t relativeSteps = 0;
|
||||
relativeSteps = (int32_t)position - currentPos;
|
||||
|
||||
//wait if direction needs to change
|
||||
if (getState() > IDLE){//already moving
|
||||
bool newDir = (relativeSteps < 0); // CCW if <0, else set CW
|
||||
if (ctrl.dir != newDir){ //direction differs
|
||||
STEP_LOGE("DendoStepper", "DIRECTION HOT-CHANGE NOT SUPPORTED - Waiting for move to finish...");
|
||||
while (getState() > IDLE) vTaskDelay(5); //wait for move to finish
|
||||
}
|
||||
}
|
||||
|
||||
//call runPos with new target position
|
||||
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)
|
||||
@@ -195,6 +214,37 @@ void DendoStepper::setSpeedMm(uint32_t speed, uint16_t accT, uint16_t decT)
|
||||
STEP_LOGI("DendoStepper", "Speed set: v=%d mm/s t+=%d s t-=%d s", speed, accT, decT);
|
||||
}
|
||||
|
||||
//CUSTOM - change speed while running
|
||||
//FIXME: this approach does not work, since calc function would have to be run after change, this will mess up target steps...
|
||||
//void DendoStepper::changeSpeed(uint32_t speed)
|
||||
//{
|
||||
// //TODO reduce duplicate code (e.g. call setSpeed function)
|
||||
// //change speed
|
||||
// ctrl.speed = speed;
|
||||
// //change status to ACC/DEC
|
||||
// STEP_LOGI("DendoStepper", "Speed changed: from v=%.2f rad/s to v=%.2f rad/s", ctrl.speed, speed);
|
||||
// if (speed > ctrl.speed) ctrl.status = ACC;
|
||||
// if (speed < ctrl.speed) ctrl.status = DEC;
|
||||
//}
|
||||
//
|
||||
//void DendoStepper::changeSpeedMm(uint32_t speed)
|
||||
//{
|
||||
// //TODO reduce duplicate code (e.g. call setSpeedMm function)
|
||||
// if (ctrl.stepsPerMm == 0)
|
||||
// {
|
||||
// STEP_LOGE("DendoStepper", "Steps per millimeter not set, cannot set the speed!");
|
||||
// }
|
||||
// //calc new speed
|
||||
// float speedNew = speed * ctrl.stepsPerMm;
|
||||
// //change status to ACC/DEC
|
||||
// if (speedNew > ctl.speed) ctrl.status = ACC;
|
||||
// if (speedNew < ctl.speed) ctrl.status = DEC;
|
||||
// //update speed, log output
|
||||
// ctrl.speed = speedNew;
|
||||
// STEP_LOGI("DendoStepper", "Speed changed: from v=%.2f rad/s to v=%.2f rad/s", ctrl.speed, speedNew);
|
||||
//}
|
||||
|
||||
|
||||
void DendoStepper::setStepsPerMm(uint16_t steps)
|
||||
{
|
||||
ctrl.stepsPerMm = steps;
|
||||
@@ -261,6 +311,7 @@ void DendoStepper::stop()
|
||||
}
|
||||
ctrl.runInfinite = false;
|
||||
timer_pause(conf.timer_group, conf.timer_idx); // stop the timer
|
||||
//ctrl.statusPrev = ctrl.status; //update previous status
|
||||
ctrl.status = IDLE;
|
||||
ctrl.stepCnt = 0;
|
||||
gpio_set_level((gpio_num_t)conf.stepPin, 0);
|
||||
@@ -287,10 +338,23 @@ bool DendoStepper::xISR()
|
||||
|
||||
ctrl.stepCnt++;
|
||||
|
||||
////CUSTOM: track actual precice current position
|
||||
//if (ctrl.dir) {
|
||||
// ctrl.posActual ++;
|
||||
//} else {
|
||||
// ctrl.posActual --;
|
||||
//}
|
||||
|
||||
//CUSTOM: track remaining steps for eventually resuming
|
||||
//xSemaphoreTake(semaphore_isrVariables, portMAX_DELAY);
|
||||
//ctrl.stepsRemaining = ctrl.stepCnt - ctrl.stepCnt;
|
||||
//xSemaphoreGive(semaphore_isrVariables);
|
||||
|
||||
// we are done
|
||||
if (ctrl.stepsToGo == ctrl.stepCnt && !ctrl.runInfinite)
|
||||
{
|
||||
timer_pause(conf.timer_group, conf.timer_idx); // stop the timer
|
||||
//ctrl.statusPrev = ctrl.status; //update previous status
|
||||
ctrl.status = IDLE;
|
||||
ctrl.stepCnt = 0;
|
||||
return 0;
|
||||
@@ -299,16 +363,19 @@ bool DendoStepper::xISR()
|
||||
if (ctrl.stepCnt > 0 && ctrl.stepCnt < ctrl.accEnd)
|
||||
{ // we are accelerating
|
||||
ctrl.currentSpeed += ctrl.accInc;
|
||||
//ctrl.statusPrev = ctrl.status; //update previous status
|
||||
ctrl.status = ACC; // we are accelerating, note that*/
|
||||
}
|
||||
else if (ctrl.stepCnt > ctrl.coastEnd && !ctrl.runInfinite)
|
||||
{ // we must be deccelerating then
|
||||
ctrl.currentSpeed -= ctrl.decInc;
|
||||
//ctrl.statusPrev = ctrl.status; //update previous status
|
||||
ctrl.status = DEC; // we are deccelerating
|
||||
}
|
||||
else
|
||||
{
|
||||
ctrl.currentSpeed = ctrl.targetSpeed;
|
||||
//ctrl.statusPrev = ctrl.status; //update previous status
|
||||
ctrl.status = COAST; // we are coasting
|
||||
}
|
||||
|
||||
@@ -321,17 +388,33 @@ bool DendoStepper::xISR()
|
||||
|
||||
void DendoStepper::calc(uint32_t targetSteps)
|
||||
{
|
||||
//only set initial speed if IDLE
|
||||
if(ctrl.status == 1){
|
||||
ctrl.currentSpeed = 0;
|
||||
ESP_LOGD("DendoStepper", "calc-start: reset speed to 0 (start from idle) %lf\n", ctrl.currentSpeed);
|
||||
}
|
||||
else{
|
||||
ESP_LOGD("DendoStepper", "calc start: NOT resetting speed (extend from ACC/DEC/COAST): %lf\n", ctrl.currentSpeed);
|
||||
}
|
||||
//CUSTOM reset counter if already moving
|
||||
ctrl.stepCnt = 0; //FIXME bugs when set 0 while ISR reads/runs? mutex
|
||||
|
||||
ctrl.accSteps = 0.5 * ctrl.acc * (ctrl.speed / ctrl.acc) * (ctrl.speed / ctrl.acc);
|
||||
|
||||
//steps from ctrl.speed -> 0:
|
||||
ctrl.decSteps = 0.5 * ctrl.dec * (ctrl.speed / ctrl.dec) * (ctrl.speed / ctrl.dec);
|
||||
ESP_LOGD("DendoStepper", "decSteps: %d currspeed: %lf, ctrlSpeed: %lf\n", ctrl.decSteps, ctrl.currentSpeed, ctrl.speed);
|
||||
//steps from 0 -> ctrl.speed:
|
||||
//ctrl.accSteps = 0.5 * ctrl.acc * (ctrl.speed / ctrl.acc) * (ctrl.speed / ctrl.acc);
|
||||
//steps from ctrl.currentSpeed -> ctrl.speed:
|
||||
ctrl.accSteps = 0.5 * ctrl.acc * (ctrl.speed / ctrl.acc) * (ctrl.speed / ctrl.acc) * (ctrl.speed - ctrl.currentSpeed) / ctrl.speed;
|
||||
ESP_LOGD("DendoStepper", "accSteps: %d currspeed: %lf, ctrlSpeed: %lf\n", ctrl.accSteps, ctrl.currentSpeed, ctrl.speed);
|
||||
|
||||
if (targetSteps < (ctrl.decSteps + ctrl.accSteps))
|
||||
{
|
||||
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.accSteps = 0.5 * ctrl.acc * (ctrl.speed / ctrl.acc) * (ctrl.speed / ctrl.acc);
|
||||
ctrl.accSteps = 0.5 * ctrl.acc * (ctrl.speed / ctrl.acc) * (ctrl.speed / ctrl.acc) * (ctrl.speed - ctrl.currentSpeed) / ctrl.speed;
|
||||
ctrl.decSteps = 0.5 * ctrl.dec * (ctrl.speed / ctrl.dec) * (ctrl.speed / ctrl.dec);
|
||||
}
|
||||
|
||||
@@ -339,13 +422,27 @@ void DendoStepper::calc(uint32_t targetSteps)
|
||||
ctrl.coastEnd = targetSteps - ctrl.decSteps;
|
||||
ctrl.targetSpeed = ctrl.speed;
|
||||
|
||||
ctrl.accInc = ctrl.targetSpeed / (double)ctrl.accSteps;
|
||||
ctrl.accInc = (ctrl.targetSpeed - ctrl.currentSpeed) / (double)ctrl.accSteps;
|
||||
ctrl.decInc = ctrl.targetSpeed / (double)ctrl.decSteps;
|
||||
|
||||
//only set initial speed if IDLE
|
||||
if(ctrl.status == 1){
|
||||
ctrl.currentSpeed = ctrl.accInc;
|
||||
ESP_LOGD("DendoStepper", "`reset curr speeed to accinc: %lf\n", ctrl.currentSpeed);
|
||||
ESP_LOGD("DendoStepper", "status=%d setting speed to initial value: %lf\n",ctrl.status, ctrl.currentSpeed);
|
||||
}
|
||||
else{
|
||||
ESP_LOGD("DendoStepper", "status=%d NOT resetting speed to initial value %lf\n",ctrl.status, 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);
|
||||
//debug log output
|
||||
ESP_LOGD("DendoStepper", "accSteps: %d, accInc: %lf, decSteps: %d, decInc: %lf",
|
||||
ctrl.accSteps, ctrl.accInc, ctrl.decSteps, ctrl.decInc);
|
||||
ESP_LOGD("DendoStepper", "speedNow=%.1f, speedTarget=%.1f, accEnd=%d, coastEnd=%d, accSteps=%d, accInc=%.3f\n",
|
||||
ctrl.currentSpeed, ctrl.targetSpeed, ctrl.accEnd, ctrl.coastEnd, ctrl.accSteps, ctrl.accInc);
|
||||
ESP_LOGD("DendoStepper", "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);
|
||||
}
|
||||
|
||||
@@ -29,6 +29,7 @@
|
||||
#include "freertos/task.h"
|
||||
#include "esp_timer.h"
|
||||
#include "math.h"
|
||||
#include "freertos/semphr.h"
|
||||
|
||||
//#define STEP_DEBUG
|
||||
|
||||
@@ -94,6 +95,9 @@ typedef struct
|
||||
float dec = 100; // decceleration in rad*second^-2
|
||||
uint32_t accSteps = 0;
|
||||
uint32_t decSteps = 0;
|
||||
int32_t stepsRemaining = 0;
|
||||
//uint64_t posActual = 0; //actual current pos incremented at every step
|
||||
uint8_t statusPrev = DISABLED; //FIXME currently unused
|
||||
uint8_t status = DISABLED;
|
||||
bool dir = CW;
|
||||
bool runInfinite = false;
|
||||
@@ -108,6 +112,7 @@ private:
|
||||
ctrl_var_t ctrl;
|
||||
esp_timer_handle_t dyingTimer;
|
||||
TaskHandle_t enTask;
|
||||
SemaphoreHandle_t semaphore_isrVariables = NULL;
|
||||
uint64_t currentPos = 0; // absolute position
|
||||
bool timerStarted = 0;
|
||||
|
||||
@@ -208,6 +213,9 @@ public:
|
||||
*/
|
||||
void setSpeedMm(uint32_t speed, uint16_t accT, uint16_t decT);
|
||||
|
||||
//CUSTOM: change speed while running
|
||||
void changeSpeedMm(uint32_t speed);
|
||||
|
||||
/**
|
||||
* @brief Set steps per 1 mm of linear movement
|
||||
*
|
||||
|
||||
File diff suppressed because one or more lines are too long
@@ -8,7 +8,6 @@ idf_component_register(
|
||||
"display.cpp"
|
||||
"cutter.cpp"
|
||||
"switchesAnalog.cpp"
|
||||
"stepper.cpp"
|
||||
"guide-stepper.cpp"
|
||||
"encoder.cpp"
|
||||
INCLUDE_DIRS
|
||||
|
||||
@@ -85,7 +85,7 @@ extern "C" {
|
||||
//----- stepper config -----
|
||||
//--------------------------
|
||||
//enable stepper test mode (dont start control and encoder task)
|
||||
#define STEPPER_TEST
|
||||
//#define STEPPER_TEST
|
||||
#define STEPPER_STEP_PIN GPIO_NUM_18 //mos1
|
||||
#define STEPPER_DIR_PIN GPIO_NUM_16 //ST3
|
||||
#define STEPPER_EN_PIN GPIO_NUM_0 //not connected (-> stepper always on)
|
||||
|
||||
@@ -7,10 +7,11 @@ extern "C"
|
||||
#include "driver/adc.h"
|
||||
}
|
||||
|
||||
#include "stepper.hpp"
|
||||
#include "DendoStepper.h"
|
||||
#include "config.hpp"
|
||||
#include "guide-stepper.hpp"
|
||||
#include "encoder.hpp"
|
||||
#include "gpio_evaluateSwitch.hpp"
|
||||
|
||||
|
||||
|
||||
@@ -23,7 +24,7 @@ extern "C"
|
||||
#define STEPPER_TEST_TRAVEL 65 //mm
|
||||
//
|
||||
#define MIN_MM 0
|
||||
#define MAX_MM 60
|
||||
#define MAX_MM 110 //60
|
||||
#define POS_MAX_STEPS MAX_MM * STEPPER_STEPS_PER_MM
|
||||
#define POS_MIN_STEPS MIN_MM * STEPPER_STEPS_PER_MM
|
||||
|
||||
@@ -31,8 +32,9 @@ extern "C"
|
||||
#define SPEED_MIN 2.0 //mm/s
|
||||
#define SPEED_MAX 60.0 //mm/s
|
||||
|
||||
#define ACCEL_MS 100.0 //ms from 0 to max
|
||||
#define DECEL_MS 90.0 //ms from max to 0
|
||||
#define SPEED 10 //35, 100, 50 rev
|
||||
#define ACCEL_MS 800.0 //ms from 0 to max
|
||||
#define DECEL_MS 500.0 //ms from max to 0
|
||||
|
||||
#define STEPPER_STEPS_PER_ROT 1600
|
||||
#define STEPPER_STEPS_PER_MM STEPPER_STEPS_PER_ROT/4
|
||||
@@ -46,9 +48,11 @@ extern "C"
|
||||
//----------------------
|
||||
//----- variables ------
|
||||
//----------------------
|
||||
static DendoStepper step;
|
||||
static const char *TAG = "stepper"; //tag for logging
|
||||
|
||||
static bool stepp_direction = true;
|
||||
static bool dir = true, dirPrev; //TODO local variables in travelSteps?
|
||||
static uint32_t posNow = 0;
|
||||
|
||||
|
||||
@@ -56,98 +60,114 @@ static uint32_t posNow = 0;
|
||||
//----------------------
|
||||
//----- functions ------
|
||||
//----------------------
|
||||
////move axis certain Steps (relative) between left and right or reverse when negative
|
||||
//void travelSteps(int stepsTarget){
|
||||
// //posNow = step.getPositionMm(); //not otherwise controlled, so no update necessary
|
||||
// int stepsToGo, remaining;
|
||||
//
|
||||
// stepsToGo = abs(stepsTarget);
|
||||
// if(stepsTarget < 0) stepp_direction = !stepp_direction; //invert direction in reverse mode
|
||||
//
|
||||
// while (stepsToGo != 0){
|
||||
// //--- currently moving right ---
|
||||
// if (stepp_direction == true){ //currently moving right
|
||||
// remaining = POS_MAX_STEPS - posNow; //calc remaining distance fom current position to limit
|
||||
// if (stepsToGo > remaining){ //new distance will exceed limit
|
||||
// //....step.runAbs (POS_MAX_STEPS); //move to limit
|
||||
// //....while(step.getState() != 1) vTaskDelay(1); //wait for move to finish
|
||||
// posNow = POS_MAX_STEPS;
|
||||
// stepp_direction = false; //change current direction for next iteration
|
||||
// stepsToGo = stepsToGo - remaining; //decrease target length by already traveled distance
|
||||
// ESP_LOGI(TAG, " --- moved to max -> change direction (L) --- \n ");
|
||||
// }
|
||||
// else { //target distance does not reach the limit
|
||||
// //....step.runAbs (posNow + stepsToGo); //move by (remaining) distance to reach target length
|
||||
// //....while(step.getState() != 1) vTaskDelay(1); //wait for move to finish
|
||||
// ESP_LOGD(TAG, "moving to %d\n", posNow+stepsToGo);
|
||||
// posNow += stepsToGo;
|
||||
// stepsToGo = 0; //finished, reset target length (could as well exit loop/break)
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// //--- currently moving left ---
|
||||
// else {
|
||||
// remaining = posNow - POS_MIN_STEPS;
|
||||
// if (stepsToGo > remaining){
|
||||
// //....step.runAbs (POS_MIN_STEPS);
|
||||
// //....while(step.getState() != 1) vTaskDelay(2); //wait for move to finish
|
||||
// posNow = POS_MIN_STEPS;
|
||||
// stepp_direction = true;
|
||||
// stepsToGo = stepsToGo - remaining;
|
||||
// ESP_LOGI(TAG, " --- moved to min -> change direction (R) --- \n ");
|
||||
// }
|
||||
// else {
|
||||
// //....step.runAbs (posNow - stepsToGo); //when moving left the coordinate has to be decreased
|
||||
// while(step.getState() != 1) vTaskDelay(2); //wait for move to finish
|
||||
// ESP_LOGD(TAG, "moving to %d\n", posNow - stepsToGo);
|
||||
// posNow -= stepsToGo;
|
||||
// stepsToGo = 0;
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// if(stepsTarget < 0) stepp_direction = !stepp_direction; //undo inversion of stepp_direction after reverse mode is finished
|
||||
// return;
|
||||
//}
|
||||
//
|
||||
//
|
||||
////move axis certain Mm (relative) between left and right or reverse when negative
|
||||
//void travelMm(int length){
|
||||
// travelSteps(length * STEPPER_STEPS_PER_MM);
|
||||
//}
|
||||
//
|
||||
//
|
||||
////define zero/start position
|
||||
////currently crashes into hardware limitation for certain time
|
||||
////TODO: limit switch
|
||||
//void home() {
|
||||
// ESP_LOGW(TAG, "auto-home...");
|
||||
// //....step.setSpeedMm(100, 500, 10);
|
||||
// //....step.runInf(1);
|
||||
// vTaskDelay(1500 / portTICK_PERIOD_MS);
|
||||
// //....step.stop();
|
||||
// //....step.resetAbsolute();
|
||||
// ESP_LOGW(TAG, "auto-home finished");
|
||||
//}
|
||||
//move axis certain Steps (relative) between left and right or reverse when negative
|
||||
void travelSteps(int stepsTarget){
|
||||
//posNow = step.getPositionMm(); //not otherwise controlled, so no update necessary
|
||||
int stepsToGo, remaining;
|
||||
|
||||
stepsToGo = abs(stepsTarget);
|
||||
if(stepsTarget < 0) stepp_direction = !stepp_direction; //invert direction in reverse mode
|
||||
|
||||
|
||||
while (stepsToGo != 0){
|
||||
|
||||
//--- wait if direction changed ---
|
||||
//if (dirPrev != dir){
|
||||
// ESP_LOGW(TAG, " dir-change detected - waiting for move to finish \n ");
|
||||
// while(step.getState() != 1) vTaskDelay(1); //wait for move to finish
|
||||
//}
|
||||
|
||||
//--- currently moving right ---
|
||||
if (stepp_direction == true){ //currently moving right
|
||||
remaining = POS_MAX_STEPS - posNow; //calc remaining distance fom current position to limit
|
||||
if (stepsToGo > remaining){ //new distance will exceed limit
|
||||
step.runAbs (POS_MAX_STEPS); //move to limit
|
||||
dirPrev = dir;
|
||||
dir = 1;
|
||||
//while(step.getState() != 1) vTaskDelay(1); //wait for move to finish
|
||||
posNow = POS_MAX_STEPS;
|
||||
stepp_direction = false; //change current direction for next iteration
|
||||
stepsToGo = stepsToGo - remaining; //decrease target length by already traveled distance
|
||||
ESP_LOGI(TAG, " --- moved to max -> change direction (L) --- \n ");
|
||||
}
|
||||
else { //target distance does not reach the limit
|
||||
step.runAbs (posNow + stepsToGo); //move by (remaining) distance to reach target length
|
||||
dirPrev = dir;
|
||||
dir = 1;
|
||||
//-- dont wait for move to finish since moves in same direction get merged --
|
||||
//while(step.getState() != 1) vTaskDelay(1); //wait for move to finish
|
||||
ESP_LOGD(TAG, "moving to %d\n", posNow+stepsToGo);
|
||||
posNow += stepsToGo;
|
||||
stepsToGo = 0; //finished, reset target length (could as well exit loop/break)
|
||||
}
|
||||
}
|
||||
|
||||
//--- currently moving left ---
|
||||
else {
|
||||
remaining = posNow - POS_MIN_STEPS;
|
||||
if (stepsToGo > remaining){
|
||||
step.runAbs (POS_MIN_STEPS);
|
||||
dirPrev = dir;
|
||||
dir = 0;
|
||||
//while(step.getState() != 1) vTaskDelay(2); //wait for move to finish
|
||||
posNow = POS_MIN_STEPS;
|
||||
stepp_direction = true;
|
||||
stepsToGo = stepsToGo - remaining;
|
||||
ESP_LOGI(TAG, " --- moved to min -> change direction (R) --- \n ");
|
||||
}
|
||||
else {
|
||||
step.runAbs (posNow - stepsToGo); //when moving left the coordinate has to be decreased
|
||||
dirPrev = dir;
|
||||
dir = 0;
|
||||
//-- dont wait for move to finish since moves in same direction get merged --
|
||||
//while(step.getState() != 1) vTaskDelay(2); //wait for move to finish
|
||||
ESP_LOGD(TAG, "moving to %d\n", posNow - stepsToGo);
|
||||
posNow -= stepsToGo;
|
||||
stepsToGo = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
if(stepsTarget < 0) stepp_direction = !stepp_direction; //undo inversion of stepp_direction after reverse mode is finished
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
//move axis certain Mm (relative) between left and right or reverse when negative
|
||||
void travelMm(int length){
|
||||
travelSteps(length * STEPPER_STEPS_PER_MM);
|
||||
}
|
||||
|
||||
|
||||
//define zero/start position
|
||||
//currently crashes into hardware limitation for certain time
|
||||
//TODO: limit switch
|
||||
void home() {
|
||||
ESP_LOGW(TAG, "auto-home...");
|
||||
step.setSpeedMm(100, 500, 10);
|
||||
step.runInf(1);
|
||||
vTaskDelay(1500 / portTICK_PERIOD_MS);
|
||||
step.stop();
|
||||
step.resetAbsolute();
|
||||
ESP_LOGW(TAG, "auto-home finished");
|
||||
}
|
||||
|
||||
|
||||
//initialize/configure stepper instance
|
||||
void init_stepper() {
|
||||
// ESP_LOGW(TAG, "initializing stepper...");
|
||||
// DendoStepper_config_t step_cfg = {
|
||||
// .stepPin = STEPPER_STEP_PIN,
|
||||
// .dirPin = STEPPER_DIR_PIN,
|
||||
// .enPin = STEPPER_EN_PIN,
|
||||
// .timer_group = TIMER_GROUP_0,
|
||||
// .timer_idx = TIMER_0,
|
||||
// .miStep = MICROSTEP_32,
|
||||
// .stepAngle = 1.8};
|
||||
// //....step.config(&step_cfg);
|
||||
// //....step.init();
|
||||
//
|
||||
// //....step.setSpeed(1000, 1000, 1000); //random default speed
|
||||
// //....step.setStepsPerMm(STEPPER_STEPS_PER_MM); //guide: 4mm/rot
|
||||
ESP_LOGW(TAG, "initializing stepper...");
|
||||
DendoStepper_config_t step_cfg = {
|
||||
.stepPin = STEPPER_STEP_PIN,
|
||||
.dirPin = STEPPER_DIR_PIN,
|
||||
.enPin = STEPPER_EN_PIN,
|
||||
.timer_group = TIMER_GROUP_0,
|
||||
.timer_idx = TIMER_0,
|
||||
.miStep = MICROSTEP_32,
|
||||
.stepAngle = 1.8};
|
||||
step.config(&step_cfg);
|
||||
step.init();
|
||||
|
||||
stepper_init();
|
||||
step.setSpeed(1000, 1000, 1000); //random default speed
|
||||
step.setStepsPerMm(STEPPER_STEPS_PER_MM); //guide: 4mm/rot
|
||||
}
|
||||
|
||||
|
||||
@@ -156,7 +176,7 @@ void updateSpeedFromAdc() {
|
||||
int potiRead = gpio_readAdc(ADC_CHANNEL_POTI); //0-4095 GPIO34
|
||||
double poti = potiRead/4095.0;
|
||||
int speed = poti*(SPEED_MAX-SPEED_MIN) + SPEED_MIN;
|
||||
//....step.setSpeedMm(speed, ACCEL_MS, DECEL_MS);
|
||||
step.setSpeedMm(speed, ACCEL_MS, DECEL_MS);
|
||||
ESP_LOGW(TAG, "poti: %d (%.2lf%%), set speed to: %d", potiRead, poti*100, speed);
|
||||
}
|
||||
|
||||
@@ -167,8 +187,23 @@ void updateSpeedFromAdc() {
|
||||
//----------------------------
|
||||
void task_stepper_test(void *pvParameter)
|
||||
{
|
||||
stepper_init();
|
||||
int state = 0;
|
||||
init_stepper();
|
||||
home();
|
||||
step.setSpeedMm(SPEED, ACCEL_MS, DECEL_MS);
|
||||
//--- move from left to right repeatedly ---
|
||||
// while (1) {
|
||||
// updateSpeedFromAdc();
|
||||
// step.runPosMm(STEPPER_TEST_TRAVEL);
|
||||
// while(step.getState() != 1) vTaskDelay(2);
|
||||
// ESP_LOGI(TAG, "finished moving right => moving left");
|
||||
|
||||
// 10updateSpeedFromAdc();
|
||||
// step.runPosMm(-STEPPER_TEST_TRAVEL);
|
||||
// while(step.getState() != 1) vTaskDelay(2); //1=idle
|
||||
// ESP_LOGI(TAG, "finished moving left => moving right");
|
||||
// }
|
||||
|
||||
//--- control stepper using preset buttons ---
|
||||
while(1){
|
||||
vTaskDelay(20 / portTICK_PERIOD_MS);
|
||||
|
||||
@@ -183,105 +218,90 @@ void task_stepper_test(void *pvParameter)
|
||||
SW_CUT.handle();
|
||||
SW_AUTO_CUT.handle();
|
||||
|
||||
//cycle through test commands with one button
|
||||
if (SW_RESET.risingEdge) {
|
||||
switch (state){
|
||||
case 0:
|
||||
stepper_setTargetPosMm(50);
|
||||
//stepper_setTargetPosSteps(1000);
|
||||
state++;
|
||||
break;
|
||||
case 1:
|
||||
stepper_setTargetPosMm(80);
|
||||
//stepper_setTargetPosSteps(100);
|
||||
state++;
|
||||
break;
|
||||
case 2:
|
||||
stepper_setTargetPosMm(20);
|
||||
//stepper_setTargetPosSteps(100);
|
||||
state++;
|
||||
break;
|
||||
case 3:
|
||||
stepper_setTargetPosMm(60);
|
||||
//stepper_setTargetPosSteps(2000);
|
||||
state = 0;
|
||||
break;
|
||||
ESP_LOGI(TAG, "button - stop stepper\n ");
|
||||
buzzer.beep(1, 1000, 100);
|
||||
step.stop();
|
||||
}
|
||||
if (SW_PRESET1.risingEdge) {
|
||||
ESP_LOGI(TAG, "button - moving right\n ");
|
||||
buzzer.beep(2, 300, 100);
|
||||
step.setSpeedMm(SPEED, ACCEL_MS, DECEL_MS);
|
||||
step.runPosMm(15);
|
||||
}
|
||||
if (SW_PRESET3.risingEdge) {
|
||||
ESP_LOGI(TAG, "button - moving left\n ");
|
||||
buzzer.beep(1, 500, 100);
|
||||
step.setSpeedMm(SPEED, ACCEL_MS, DECEL_MS);
|
||||
step.runPosMm(-15);
|
||||
}
|
||||
if (SW_PRESET2.risingEdge) {
|
||||
buzzer.beep(1, 100, 100);
|
||||
ESP_LOGW(TAG, "button - current state: %d\n, pos: %llu", (int)step.getState(), step.getPositionMm());
|
||||
}
|
||||
}
|
||||
}
|
||||
// if (SW_PRESET1.risingEdge) {
|
||||
// buzzer.beep(2, 300, 100);
|
||||
// stepperSw_setTargetSteps(1000);
|
||||
// }
|
||||
// if (SW_PRESET2.risingEdge) {
|
||||
// buzzer.beep(1, 500, 100);
|
||||
// stepperSw_setTargetSteps(10000);
|
||||
// }
|
||||
// if (SW_PRESET3.risingEdge) {
|
||||
// buzzer.beep(1, 100, 100);
|
||||
// stepperSw_setTargetSteps(30000);
|
||||
// }
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
//----------------------------
|
||||
//----- TASK stepper-ctl -----
|
||||
//----------------------------
|
||||
void task_stepper_ctl(void *pvParameter)
|
||||
{
|
||||
// //variables
|
||||
// int encStepsNow = 0; //get curret steps of encoder
|
||||
// int encStepsPrev = 0; //steps at last check
|
||||
// int encStepsDelta = 0; //steps changed since last iteration
|
||||
//
|
||||
// double cableLen = 0;
|
||||
// double travelStepsExact = 0; //steps axis has to travel
|
||||
// double travelStepsPartial = 0;
|
||||
// int travelStepsFull = 0;
|
||||
// double travelMm = 0;
|
||||
// double turns = 0;
|
||||
//
|
||||
// float potiModifier;
|
||||
//
|
||||
// init_stepper();
|
||||
// home();
|
||||
//
|
||||
// while(1){
|
||||
// //get current length
|
||||
// encStepsNow = encoder_getSteps();
|
||||
//
|
||||
// //calculate change
|
||||
// encStepsDelta = encStepsNow - encStepsPrev; //FIXME MAJOR BUG: when resetting encoder/length in control task, diff will be huge!
|
||||
//
|
||||
// //read potentiometer and normalize (0-1) to get a variable for testing
|
||||
// potiModifier = (float) gpio_readAdc(ADC_CHANNEL_POTI) / 4095; //0-4095 -> 0-1
|
||||
// //ESP_LOGI(TAG, "current poti-modifier = %f", potiModifier);
|
||||
//
|
||||
// //calculate steps to move
|
||||
// cableLen = (double)encStepsDelta * 1000 / ENCODER_STEPS_PER_METER;
|
||||
// turns = cableLen / (PI * D_REEL);
|
||||
// travelMm = turns * D_CABLE;
|
||||
// travelStepsExact = travelMm * STEPPER_STEPS_PER_MM + travelStepsPartial; //convert mm to steps and add not moved partial steps
|
||||
// travelStepsPartial = 0;
|
||||
// travelStepsFull = (int)travelStepsExact;
|
||||
//
|
||||
// //move axis when ready to move at least 1 step
|
||||
// if (abs(travelStepsFull) > 1){
|
||||
// travelStepsPartial = fmod(travelStepsExact, 1); //save remaining partial steps to be added in the next iteration
|
||||
// ESP_LOGD(TAG, "cablelen=%.2lf, turns=%.2lf, travelMm=%.3lf, travelStepsExact: %.3lf, travelStepsFull=%d, partialStep=%.3lf", cableLen, turns, travelMm, travelStepsExact, travelStepsFull, travelStepsPartial);
|
||||
// ESP_LOGI(TAG, "MOVING %d steps", travelStepsFull);
|
||||
// //TODO: calculate variable speed for smoother movement? for example intentionally lag behind and calculate speed according to buffered data
|
||||
// //....step.setSpeedMm(35, 100, 50);
|
||||
// //testing: get speed from poti
|
||||
// //step.setSpeedMm(35, 1000*potiModifier+1, 1000*potiModifier+1);
|
||||
// travelSteps(travelStepsExact);
|
||||
// encStepsPrev = encStepsNow; //update previous length
|
||||
// }
|
||||
// else {
|
||||
// //TODO use encoder queue to only run this check at encoder event?
|
||||
// vTaskDelay(2);
|
||||
// }
|
||||
// }
|
||||
//variables
|
||||
int encStepsNow = 0; //get curret steps of encoder
|
||||
int encStepsPrev = 0; //steps at last check
|
||||
int encStepsDelta = 0; //steps changed since last iteration
|
||||
|
||||
double cableLen = 0;
|
||||
double travelStepsExact = 0; //steps axis has to travel
|
||||
double travelStepsPartial = 0;
|
||||
int travelStepsFull = 0;
|
||||
double travelMm = 0;
|
||||
double turns = 0;
|
||||
|
||||
float potiModifier;
|
||||
|
||||
init_stepper();
|
||||
home();
|
||||
|
||||
while(1){
|
||||
//get current length
|
||||
encStepsNow = encoder_getSteps();
|
||||
|
||||
//calculate change
|
||||
encStepsDelta = encStepsNow - encStepsPrev; //FIXME MAJOR BUG: when resetting encoder/length in control task, diff will be huge!
|
||||
|
||||
//read potentiometer and normalize (0-1) to get a variable for testing
|
||||
potiModifier = (float) gpio_readAdc(ADC_CHANNEL_POTI) / 4095; //0-4095 -> 0-1
|
||||
//ESP_LOGI(TAG, "current poti-modifier = %f", potiModifier);
|
||||
ESP_LOGI(TAG, "delaying stepper-ctl task by %.1f ms (poti value)", 2000 * potiModifier);
|
||||
vTaskDelay(2000 * potiModifier / portTICK_PERIOD_MS);
|
||||
|
||||
//calculate steps to move
|
||||
cableLen = (double)encStepsDelta * 1000 / ENCODER_STEPS_PER_METER;
|
||||
turns = cableLen / (PI * D_REEL);
|
||||
travelMm = turns * D_CABLE;
|
||||
travelStepsExact = travelMm * STEPPER_STEPS_PER_MM + travelStepsPartial; //convert mm to steps and add not moved partial steps
|
||||
travelStepsPartial = 0;
|
||||
travelStepsFull = (int)travelStepsExact;
|
||||
|
||||
//move axis when ready to move at least 1 step
|
||||
if (abs(travelStepsFull) > 1){
|
||||
travelStepsPartial = fmod(travelStepsExact, 1); //save remaining partial steps to be added in the next iteration
|
||||
ESP_LOGD(TAG, "cablelen=%.2lf, turns=%.2lf, travelMm=%.3lf, travelStepsExact: %.3lf, travelStepsFull=%d, partialStep=%.3lf", cableLen, turns, travelMm, travelStepsExact, travelStepsFull, travelStepsPartial);
|
||||
ESP_LOGI(TAG, "MOVING %d steps", travelStepsFull);
|
||||
//TODO: calculate variable speed for smoother movement? for example intentionally lag behind and calculate speed according to buffered data
|
||||
step.setSpeedMm(SPEED, ACCEL_MS, DECEL_MS);
|
||||
//testing: get speed from poti
|
||||
//step.setSpeedMm(35, 1000*potiModifier+1, 1000*potiModifier+1);
|
||||
travelSteps(travelStepsExact);
|
||||
encStepsPrev = encStepsNow; //update previous length
|
||||
}
|
||||
else {
|
||||
//TODO use encoder queue to only run this check at encoder event?
|
||||
vTaskDelay(2);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,8 +17,6 @@ extern "C"
|
||||
#include "guide-stepper.hpp"
|
||||
#include "encoder.hpp"
|
||||
|
||||
#include "stepper.hpp"
|
||||
|
||||
|
||||
//=================================
|
||||
//=========== functions ===========
|
||||
@@ -89,19 +87,18 @@ extern "C" void app_main()
|
||||
esp_log_level_set("switches-analog", ESP_LOG_WARN);
|
||||
esp_log_level_set("control", ESP_LOG_INFO);
|
||||
esp_log_level_set("stepper", ESP_LOG_DEBUG);
|
||||
esp_log_level_set("Dendostepper", ESP_LOG_WARN); //stepper lib
|
||||
esp_log_level_set("DendoStepper", ESP_LOG_DEBUG); //stepper lib
|
||||
esp_log_level_set("calc", ESP_LOG_WARN); //stepper lib
|
||||
|
||||
#ifdef STEPPER_TEST
|
||||
//create task for stepper testing
|
||||
xTaskCreate(task_stepper_test, "task_stepper_test", configMINIMAL_STACK_SIZE * 3, NULL, 2, NULL);
|
||||
//xTaskCreate(task_stepper_debug, "task_stepper_test", configMINIMAL_STACK_SIZE * 3, NULL, 2, NULL);
|
||||
xTaskCreate(task_stepper_test, "task_stepper_test", configMINIMAL_STACK_SIZE * 3, NULL, 5, NULL);
|
||||
#else
|
||||
//create task for controlling the machine
|
||||
xTaskCreate(task_control, "task_control", configMINIMAL_STACK_SIZE * 3, NULL, 4, NULL);
|
||||
xTaskCreate(task_control, "task_control", configMINIMAL_STACK_SIZE * 3, NULL, 5, NULL);
|
||||
|
||||
//create task for controlling the stepper
|
||||
xTaskCreate(task_stepper_ctl, "task_stepper_ctl", configMINIMAL_STACK_SIZE * 3, NULL, 2, NULL);
|
||||
//create task for controlling the machine
|
||||
xTaskCreate(task_stepper_ctl, "task_stepper_ctl", configMINIMAL_STACK_SIZE * 5, NULL, 5, NULL);
|
||||
#endif
|
||||
|
||||
//create task for handling the buzzer
|
||||
|
||||
249
main/stepper.cpp
249
main/stepper.cpp
@@ -1,249 +0,0 @@
|
||||
//custom driver for stepper motor
|
||||
#include "config.hpp"
|
||||
#include "hal/timer_types.h"
|
||||
#include <cstdint>
|
||||
#include <inttypes.h>
|
||||
|
||||
extern "C" {
|
||||
#include "driver/timer.h"
|
||||
#include "driver/gpio.h"
|
||||
#include "esp_log.h"
|
||||
}
|
||||
|
||||
//config from config.hpp
|
||||
//#define STEPPER_STEP_PIN GPIO_NUM_18 //mos1
|
||||
//#define STEPPER_DIR_PIN GPIO_NUM_16 //ST3
|
||||
|
||||
#define STEPPER_STEPS_PER_MM 200/2 //steps/mm
|
||||
#define STEPPER_SPEED_DEFAULT 20 //mm/s
|
||||
#define STEPPER_SPEED_MIN 4 //mm/s - speed at which stepper immediately starts/stops
|
||||
#define STEPPER_ACCEL_INC 3 //steps/s per cycle
|
||||
#define STEPPER_DECEL_INC 8 //steps/s per cycle
|
||||
|
||||
|
||||
#define TIMER_F 1000000ULL
|
||||
#define TICK_PER_S TIMER_S
|
||||
#define NS_TO_T_TICKS(x) (x)
|
||||
|
||||
|
||||
|
||||
//========================
|
||||
//=== global variables ===
|
||||
//========================
|
||||
static const char *TAG = "stepper-ctl"; //tag for logging
|
||||
|
||||
bool direction = 1;
|
||||
bool directionTarget = 1;
|
||||
bool timerIsRunning = false;
|
||||
bool timer_isr(void *arg);
|
||||
|
||||
static timer_group_t timerGroup = TIMER_GROUP_0;
|
||||
static timer_idx_t timerIdx = TIMER_0;
|
||||
|
||||
//TODO the below variables can be moved to isr function once debug output is no longer needed
|
||||
static uint64_t posTarget = 0;
|
||||
static uint64_t posNow = 0;
|
||||
static uint64_t stepsToGo = 0;
|
||||
static uint32_t speedMin = STEPPER_SPEED_MIN * STEPPER_STEPS_PER_MM;
|
||||
static uint32_t speedNow = speedMin;
|
||||
static int debug = 0;
|
||||
static uint32_t speedTarget = STEPPER_SPEED_DEFAULT * STEPPER_STEPS_PER_MM;
|
||||
//TODO/NOTE increment actually has to be re-calculated every run to have linear accel (because also gets called faster/slower)
|
||||
static uint32_t decel_increment = STEPPER_DECEL_INC;
|
||||
static uint32_t accel_increment = STEPPER_ACCEL_INC;
|
||||
|
||||
|
||||
|
||||
//======================
|
||||
//===== DEBUG task =====
|
||||
//======================
|
||||
void task_stepper_debug(void *pvParameter){
|
||||
while (1){
|
||||
ESP_LOGI("stepper-DEBUG",
|
||||
"timer=%d "
|
||||
"dir=%d "
|
||||
"dirTarget=%d "
|
||||
"posTarget=%llu "
|
||||
"posNow=%llu "
|
||||
"stepsToGo=%llu "
|
||||
"speedNow=%u "
|
||||
"speedTarget=%u "
|
||||
"debug=%d ",
|
||||
|
||||
timerIsRunning,
|
||||
direction,
|
||||
directionTarget,
|
||||
posTarget,
|
||||
posNow,
|
||||
stepsToGo,
|
||||
speedNow,
|
||||
speedTarget,
|
||||
debug
|
||||
);
|
||||
|
||||
vTaskDelay(300 / portTICK_PERIOD_MS);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
//=====================
|
||||
//===== set speed =====
|
||||
//=====================
|
||||
void stepper_setSpeed(uint32_t speedMmPerS) {
|
||||
ESP_LOGW(TAG, "set target speed from %u to %u mm/s (%u steps/s)",
|
||||
speedTarget, speedMmPerS, speedMmPerS * STEPPER_STEPS_PER_MM);
|
||||
speedTarget = speedMmPerS * STEPPER_STEPS_PER_MM;
|
||||
}
|
||||
|
||||
|
||||
|
||||
//==========================
|
||||
//== set target pos STEPS ==
|
||||
//==========================
|
||||
void stepper_setTargetPosSteps(uint64_t target_steps) {
|
||||
ESP_LOGW(TAG, "update target position from %llu to %llu steps (stepsNow: %llu", posTarget, target_steps, posNow);
|
||||
posTarget = target_steps;
|
||||
|
||||
// Check if the timer is currently paused
|
||||
if (!timerIsRunning){
|
||||
// If the timer is paused, start it again with the updated targetSteps
|
||||
timerIsRunning = true;
|
||||
ESP_LOGW(TAG, "starting timer because did not run before");
|
||||
ESP_ERROR_CHECK(timer_set_alarm_value(timerGroup, timerIdx, 1000));
|
||||
//timer_set_counter_value(timerGroup, timerIdx, 1000);
|
||||
ESP_ERROR_CHECK(timer_start(timerGroup, timerIdx));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
//=========================
|
||||
//=== set target pos MM ===
|
||||
//=========================
|
||||
void stepper_setTargetPosMm(uint32_t posMm){
|
||||
ESP_LOGW(TAG, "set target position to %u mm", posMm);
|
||||
stepper_setTargetPosSteps(posMm * STEPPER_STEPS_PER_MM);
|
||||
}
|
||||
|
||||
|
||||
|
||||
//========================
|
||||
//===== init stepper =====
|
||||
//========================
|
||||
void stepper_init(){
|
||||
ESP_LOGW(TAG, "init - configure struct...");
|
||||
|
||||
// Configure pulse and direction pins as outputs
|
||||
ESP_LOGW(TAG, "init - configure gpio pins...");
|
||||
gpio_set_direction(STEPPER_DIR_PIN, GPIO_MODE_OUTPUT);
|
||||
gpio_set_direction(STEPPER_STEP_PIN, GPIO_MODE_OUTPUT);
|
||||
|
||||
ESP_LOGW(TAG, "init - initialize/configure timer...");
|
||||
timer_config_t timer_conf = {
|
||||
.alarm_en = TIMER_ALARM_EN, // we need alarm
|
||||
.counter_en = TIMER_PAUSE, // dont start now lol
|
||||
.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
|
||||
};
|
||||
ESP_ERROR_CHECK(timer_init(timerGroup, timerIdx, &timer_conf)); // init the timer
|
||||
ESP_ERROR_CHECK(timer_set_counter_value(timerGroup, timerIdx, 0)); // set it to 0
|
||||
ESP_ERROR_CHECK(timer_isr_callback_add(timerGroup, timerIdx, timer_isr, (void *)timerIdx, 0));
|
||||
}
|
||||
|
||||
|
||||
|
||||
//================================
|
||||
//=== timer interrupt function ===
|
||||
//================================
|
||||
bool timer_isr(void *arg) {
|
||||
|
||||
//-----------------
|
||||
//--- variables ---
|
||||
//-----------------
|
||||
//TODO used (currently global) variables here
|
||||
|
||||
//-----------------------------------
|
||||
//--- define direction, stepsToGo ---
|
||||
//-----------------------------------
|
||||
//Note: the idea is that the stepper has to decelerate to min speed first before changeing the direction
|
||||
//define target direction depending on position difference
|
||||
bool directionTarget = posTarget > posNow ? 1 : 0;
|
||||
//DIRECTION DIFFERS (change)
|
||||
if ( (direction != directionTarget) && (posTarget != posNow)) {
|
||||
if (stepsToGo == 0){ //standstill
|
||||
direction = directionTarget; //switch direction
|
||||
gpio_set_level(STEPPER_DIR_PIN, direction);
|
||||
stepsToGo = abs(int64_t(posTarget - posNow));
|
||||
} else {
|
||||
//set to minimun decel steps
|
||||
stepsToGo = (speedNow - speedMin) / decel_increment;
|
||||
}
|
||||
}
|
||||
//NORMAL (any direction 0/1)
|
||||
else {
|
||||
stepsToGo = abs(int64_t(posTarget - posNow));
|
||||
}
|
||||
|
||||
//--------------------
|
||||
//--- define speed ---
|
||||
//--------------------
|
||||
//FIXME noticed crash: division by 0 when min speed > target speed
|
||||
uint64_t stepsDecelRemaining = (speedNow - speedMin) / decel_increment;
|
||||
//DECELERATE
|
||||
if (stepsToGo <= stepsDecelRemaining) {
|
||||
//FIXME if stepsToGo gets updated (lowered) close to target while close to target, the stepper may stop too fast -> implement possibility to 'overshoot and reverse'?
|
||||
if ((speedNow - speedMin) > decel_increment) {
|
||||
speedNow -= decel_increment;
|
||||
} else {
|
||||
speedNow = speedMin; //PAUSE HERE??? / irrelevant?
|
||||
}
|
||||
}
|
||||
//ACCELERATE
|
||||
else if (speedNow < speedTarget) {
|
||||
speedNow += accel_increment;
|
||||
if (speedNow > speedTarget) speedNow = speedTarget;
|
||||
}
|
||||
//COASTING
|
||||
else { //not relevant?
|
||||
speedNow = speedTarget;
|
||||
}
|
||||
|
||||
//-------------------------------
|
||||
//--- update timer, increment ---
|
||||
//-------------------------------
|
||||
//AT TARGET -> STOP
|
||||
if (stepsToGo == 0) {
|
||||
timer_pause(timerGroup, timerIdx);
|
||||
timerIsRunning = false;
|
||||
speedNow = speedMin;
|
||||
return 1;
|
||||
}
|
||||
|
||||
//STEPS REMAINING -> NEXT STEP
|
||||
//update timer with new speed
|
||||
ESP_ERROR_CHECK(timer_set_alarm_value(timerGroup, timerIdx, TIMER_F / speedNow));
|
||||
|
||||
//generate pulse
|
||||
GPIO.out_w1ts = (1ULL << STEPPER_STEP_PIN); //turn on (fast)
|
||||
ets_delay_us(10);
|
||||
GPIO.out_w1tc = (1ULL << STEPPER_STEP_PIN); //turn off (fast)
|
||||
|
||||
//increment pos
|
||||
stepsToGo --;
|
||||
if (direction == 1){
|
||||
posNow ++;
|
||||
} else {
|
||||
//prevent underflow FIXME this case should not happen in the first place?
|
||||
if (posNow != 0){
|
||||
posNow --;
|
||||
} else {
|
||||
ESP_LOGE(TAG,"isr: posNow would be negative - ignoring decrement");
|
||||
}
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,13 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
//init stepper pins and timer
|
||||
void stepper_init();
|
||||
//set absolute target position in steps
|
||||
void stepper_setTargetPosSteps(uint64_t steps);
|
||||
//set absolute target position in millimeters
|
||||
void stepper_setTargetPosMm(uint32_t posMm);
|
||||
//set target speed in millimeters per second
|
||||
void stepper_setSpeed(uint32_t speedMmPerS);
|
||||
|
||||
//task that periodically logs variables for debugging stepper driver
|
||||
void task_stepper_debug(void *pvParameter);
|
||||
Reference in New Issue
Block a user