eldendiss / dendostepper Goto Github PK
View Code? Open in Web Editor NEWStepper motor API for esp-idf.
License: GNU General Public License v3.0
Stepper motor API for esp-idf.
License: GNU General Public License v3.0
Hi!
Thanks so much for the library, it works great!
Please help me with spining the motor all the time and only control the direction and speed.
I have tried the following, but my understanding of timer operation is not enough to relay on my own.
The motor is moving with jerks.
void stepperTask(void *pvParam) {
static const TickType_t xBlockTime = pdMS_TO_TICKS(50);
dStep.init(dConfig.step_p, dConfig.dir_p, dConfig.en_p, dConfig.timer_group,
dConfig.timer_idx, MICROSTEP_1, 200);
dStep.setSpeed(1000, 1000);
// ESP_LOGW(STEPPER_TAG, "stepper!");
bool dir = true;
uint32_t notify_value;
while (true) {
if (xTaskNotifyWait(0, 0, ¬ify_value, 0) == pdTRUE) {
ESP_LOGI(STEPPER_TAG, "ENC: %d", value);
dir = (int16_t)notify_value > 0;
if (value != 0) {
dStep.setSpeed(1000 * abs(notify_value), accT);
}
}
dStep.runPermanent(dir);
vTaskDelay(xBlockTime);
}
}
// DendoStepper Class function.
esp_err_t DendoStepper::runPermanent(bool dir)
{
ctrl.status=ACC;
setDir(dir);
calc(ctrl.speed, ctrl.acc, abs(1000)); // 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;
}
Is your feature request related to a problem? Please describe.
Proposed by @cedricwritescode
Describe the solution you'd like
Pretty self explanatory. This configuration could be in a constructor in refactored code.
Is your feature request related to a problem? Please describe.
When starting a movement, it will get executed asynchronously (using the gptimer ISR). To check that the movement is completed, however, you need to poll the status.
Describe the solution you'd like
The library should tell the main program that the motor movement finished, by means of a callback of some sorts. Maybe the esp_event library could be used.
Describe alternatives you've considered
FreeRTOS constructs could be used as well, like binary Semaphores, queues or task notifications.
Additional context
Is your feature request related to a problem? Please describe.
Related to ideas presented by @cedricwritescode to make the library usage more clear and support more stepping drivers.
Describe the solution you'd like
Refactor current DendoStepper class, maybe implement separate axis class for linear motion. Initialization of pins and other parameters should be in a constructor. Update documentation in README and update the example code.
Additional context
This changes would be breaking backwards compatibility.
Describe the bug
I noticed that the position of my stepper motor changes over time when I tried turning one full rotation repeatedly. Turns out, the ISR misses one flank per executed movement.
To Reproduce
Use example with any step count (a lower step count makes it more easily visible)
I used the following code:
#include <stdio.h>
#include "DendoStepper.h"
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "esp_log.h"
DendoStepper step;
DendoStepper step1;
extern "C" void app_main(void)
{
DendoStepper_config_t step_cfg = {
.stepPin = 2,
.dirPin = 4,
.enPin = 5,
.miStep = MICROSTEP_1,
.stepAngle = 1.8};
step.config(&step_cfg);
step.init();
step.setSpeed(1000, 50, 50);
step.setStepsPerMm(10);
while (1)
{
//can't do 1 or 2 steps, it will not move!!
step.runPos(10);
vTaskDelay(8000 / portTICK_PERIOD_MS);
}
}
Expected behavior
One movement produces the exact amunt of negative and positive edges (in my case 10 negative edges).
Screenshots
The existing code causes this behavior:
Changing the ISR results in the correction of this issue:
HW (please complete the following information):
Pull Request
See here
Describe the bug
Hello there I was trying to test the example with the TMC2208 but not able to start the stepper motor.
But a simple gpio control works
The delay between the the high and low pulse should be 250 ms
HW (please complete the following information):
Describe the bug
When stopping an ongoing movement, the current position variable will reflect the position before the start of the movement, instead of the actual position of the stepper motor.
To Reproduce
#include <stdio.h>
#include "DendoStepper.h"
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "esp_log.h"
DendoStepper step;
extern "C" void app_main(void)
{
DendoStepper_config_t step_cfg = {
.stepPin = 2,
.dirPin = 4,
.enPin = 5,
.miStep = MICROSTEP_1,
.stepAngle = 1.8
};
step.config(&step_cfg);
step.init();
step.setStepsPerMm(40);
step.setSpeedMm(5, 1000, 1000);
//Check behavior of position with and without stop getting called
bool withStop = false;
while (1)
{
ESP_LOGI("main", "Loop run with stop: %s", withStop ? "true" : "false");
ESP_LOGI("main", "pos 1: %lld", step.getPositionMm());
step.runPosMm(50);
vTaskDelay(2500 / portTICK_PERIOD_MS);
ESP_LOGI("main", "pos 2: %lld", step.getPositionMm());
vTaskDelay(2500 / portTICK_PERIOD_MS);
if(withStop) {
step.stop();
}
ESP_LOGI("main", "pos 3: %lld", step.getPositionMm());
withStop = !withStop;
}
}
The output looks like this:
I (380) main: Loop run with stop: false
I (380) main: pos 1: 0
I (390) DendoStepper: Enabled
I (390) calc: acc end:25 coastend:1975 stepstogo:2000 speed:200.000000 acc:800.000000 int: 125000
I (2900) main: pos 2: 50
I (5400) main: pos 3: 50
I (5400) main: Loop run with stop: true
I (5400) main: pos 1: 50
W (5400) DendoStepper: Finising previous move, this command will be ignored
I (7900) main: pos 2: 50
I (10400) main: pos 3: 50
I (10400) main: Loop run with stop: false
I (10400) main: pos 1: 50
I (10400) calc: acc end:25 coastend:1975 stepstogo:2000 speed:200.000000 acc:800.000000 int: 125000
I (12910) main: pos 2: 100
I (15410) main: pos 3: 100
I (15410) main: Loop run with stop: true
I (15410) main: pos 1: 100
W (15410) DendoStepper: Finising previous move, this command will be ignored
I (17910) main: pos 2: 100
I (20410) main: pos 3: 100
Expected behavior
The current position should be valid at all times. This is required by the fact that starting a movement is done asynchronously, so the current position could be read at any time.
Screenshots
HW (please complete the following information):
Additional context
Is your feature request related to a problem? Please describe.
I find the structure of the library a bit unintuitive. Therefore I propose these changes:
Describe the solution you'd like
Separate linear movement functionality from actual motor control into different classes
The linear movement class could inherit from the actual stepper class.
Change properties of motor and motors connected to linear axes
Change microStepping and stepAngle to stepsPerRot. This would give the user more freedom to decide on microstepping values, as well as being a more descriptive property. The user could set it like (motor_steps_per_turn * controller_microsteps).
Additionally, I think stepsPerMm mixes properties of linear and stepper functionality. I propose to use feedConstant instead (i.e. mm/turn).
Simplify initialization (i.e. init, init(params), config methods)
Generally, there should be a single method the user calls for initialization. Right now there are 3 methods, which uses might be a bit ambigous.
I think the best way would be to only use the init struct, as it is more concise and adaptable than passing every config value as a method parameter. I think performing initialization in the constructor is not optimal. The reason is that a possible error during a c'tor call would be less debuggable than a runtime error.
Describe alternatives you've considered
Additional context
Is your feature request related to a problem? Please describe.
I noticed that while a motor is moving using moveInf(direction) that speed changes are not applied. Additionally, there doesn't seem to be a mechanism that allows it to decelerate to a stop, only to stop instantly (emergency stop).
Describe the solution you'd like
I'm not sure how, but ultimately, a way to adjust speed while doing an infinite move may solve both problems, but is really what I need for time based stepper movements, rather than distance. I could just adjust speed to zero to stop it gracefully perhaps. Or a stopInf()? or make stop() aware of if it's moving linearly, or moving infinite?
Additional context
The use case in this case is a milling machine power feed, in which case the distance it moves is not important since it's manually engaged or disengaged by a user. It's only the speed that it moves that's important, and the typical UI allows the user to adjust speed as a cut progresses.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.