New Stepper Motor Library

Thank you, Luni, for the detailed answer :) I already have a phototransistor (PC817-Sharp) to change the "voltage" rise, but additionally, I ordered an inverter (74HC04). Of course, it would be much better to do it in the microcontroller code.

I will check if it works because the DM805 requires a minimum 5μs delay between the pulse and direction signals. However, I think it should not be a problem if the first few steps are lost (I use microsteps, with 3200 pulses per revolution) - but I need to check.
 
Usually you would use a *HCT since the input levels are better suited for a 3.3V controller output. But, the output rating of a HC/HCT chip is a bit borderline. Your driver is specd for typically 10mA (max 16mA) input current (probably a optocoupled input). IIRC the HC/HCT output is speced for 8mA or so. The 74ACT04 I recomended above should be able to deliver some 25mA (https://www.ti.com/lit/pdf/sdyu001)

A 5µs delay after a direction change is already implemented.
 
Last edited:
Hi Luni,

I'm coming back to this project and I'm having issues and I can't figure out why.
I'm using the current library from https://github.com/luni64/TeensyStep4

With this code the motor does not turn as expected. I think higher speeds don't have this problem but I'm working with very low speeds.

Code:
#include "Arduino.h"
#include "teensystep4.h"
using namespace TS4;
Stepper s1(19, 18);
int ms = 20;  //max speed
int a = 40000;   // acc
elapsedMillis stopwatch;
IntervalTimer t1;
void onTimer() {
  Serial.printf("%6d\t%6d\n", s1.getPosition());
}
void setup() {
  Serial.begin(9600);
  TS4::begin();
  while (!Serial)
    ;
  t1.begin(onTimer, 50'000);          // print out motor positions
  stopwatch = 0;
  s1.setMaxSpeed(ms);
  s1.setAcceleration(a);
}
void loop() {
  s1.rotateAsync(20);
  s1.overrideSpeed(50);
  delay(4000);
  s1.overrideSpeed(-1);
  delay(4000);
  s1.overrideSpeed(-10);
  delay(4000);
  s1.overrideSpeed(50);
  delay(1000);
  s1.overrideSpeed(-11);
  delay(4000);
  s1.overrideSpeed(25);
  delay(1000);
  s1.stopAsync();
  delay(4000);
}

Thanks as always!

EDIT: Changed the code to a more appropriate test.
 
Last edited:
Hi Luni,
I think can finially can reproduce a bug.
Using this code, when starting a negative overrideSpeed, the motor will move positive first.
Code:
#include "Arduino.h"
#include "teensystep4.h"
using namespace TS4;
Stepper s1(19, 18);
int ms = 5333;  //max speed
int a = 4000;   // acc
elapsedMillis stopwatch;
IntervalTimer t1;
void onTimer() {
  Serial.println(s1.getPosition());
}
void setup() {
  Serial.begin(9600);
  TS4::begin();
  while (!Serial)
    ;
  t1.begin(onTimer, 50'000);          // print out motor positions
  stopwatch = 0;
  s1.setMaxSpeed(ms);
  s1.setAcceleration(a);
}
void loop() {
  s1.moveAbs(200);
  delay(2000);
  s1.rotateAsync(266);
  s1.overrideSpeed(-0.5);
  delay(2000);
  s1.stopAsync();
  delay(4000);
}

You can see the "blips" here:
motor.jpg


Ultimately as we're using this on a camera pan / tilt mount, the camera goes the wrong way first.

Thanks again!
Col
 
Fortunately I'm able to work around it by testing if the incoming joystick move is negative or positive and change the
rotateAsync to a negative speed, and inverting all overrideSpeed input.
 
Thanks for spotting this. I'll have a look whats going on there. Might take a couple of days.
 
Hi there.

I have a project where I need to transition smoothly between many target positions. I've currently been sending a group of x4 steppers to a specific amount of steps and would like to queue up the next set of positions for the steppers to go to instead of decelerating to a stop.

Is there a way to achieve this using setTargetAbs(), or would I have to use Rotate?

I've been using a forked version of TeensyStep4 where I successfully implemented 74HCT595 level shifters to replace the typical digitalWriteFast().

Thank you!
 
After a bit of digging, I found an old thread between a user named BlueGene00 and Luni: https://github.com/luni64/TeensyStep/issues/139

BlueGene00 was doing the exact same project that I am doing, but I wasn't able to successfully contact him. From what it seems, I first need to implement no acceleration in the code. Whereas the original TeensyStep library implemented templates for different accelerators, the approach seems differently in TeensyStep4. I tried simply setting setAcceleration() to zero for all steppers but that didn't seem to work. I then went digging into the code to see if there was a culprit for setting the acceleration to 0 but couldn't find anything obviously suspicious (I probably missed it somewhere).

Is there any intent to implement accelerator templates into teensystep4? I'd be more than happy to be a guinea pig.

The hope is that if I get no acceleration working, I'd like to invoke a callback to the main function that runs the steppers with a step target matrix as per the discussion I linked above:

Code:
constexpr pos path[] = {
    {3200, 3200},
    {   0,    0},
    {5000, -1000},
    { 200, -3200},
    { 0, 0},
};

(This is an example from the discussion)

This is the function I was hoping to invoke in the callback:
Code:
void runMoco(){
  for(int i = 1; i < NUM_KEYFRAMES; i++){ //change back to i=1 if testing with delta
    //Serial.println("Keyframe");
    for(int j = 0; j < NUM_STEPPERS; j++) {
      int delta = kuper[i][j] - kuper[i-1][j]; //takes difference between current and next in STEPS
      //Serial.println(delta);
      prepareMovement(j, delta); //input: currStepper, steps
    }
    runAndWait(); //wait for all axes to finish keyframe(n) to keyframe(n+1) movement
  }
}

The NUM_KEYFRAMES represents the rows in the first example, and NUM_STEPPERS refers to the specific stepper motor address as represented in the columns in the first example as well.

Now I recognize that to invoke the callback, I'll have to replace the nested for loop in place of an if() statement as per example 1:
Code:
if (p < pathLength)
    {
        sx.setTargetAbs(path[p].x);
        sy.setTargetAbs(path[p].y);

        ctrl.moveAsync(sx, sy);
        p++;
    }

This is Example 1's function that would be the parameter for the subsequent callback declaration:
Code:
ctrl.setCallback(onPositionReached);

I would love to get some advice on implementing the no-accelerator templates and callbacks for TeensyStep4.

Thank you for your time!
 
I’m not sure I fully understand what you’re after. Part of what you say is really easy, and then I get confused by the rest.

The first bit sounds like you’re setting a bunch of x y coordinates and you then want to move between each pair of coordinates, moving to the next set when you’ve reached the current set.
For example, move to point A, when at point A move to point B etc…
That’s very easy as the “move” instruction is a blocking one so the next line of code will only run when the move is complete. At which point you set the target positions and move again.

I’m not sure what the “callback” stuff is for. I think this is where I lose what you’re trying to achieve.
 
I’m not sure I fully understand what you’re after. Part of what you say is really easy, and then I get confused by the rest.

The first bit sounds like you’re setting a bunch of x y coordinates and you then want to move between each pair of coordinates, moving to the next set when you’ve reached the current set.
For example, move to point A, when at point A move to point B etc…
That’s very easy as the “move” instruction is a blocking one so the next line of code will only run when the move is complete. At which point you set the target positions and move again.

I’m not sure what the “callback” stuff is for. I think this is where I lose what you’re trying to achieve.
The current issue is that by setting target positions one after the other and using the .move() function for a stepper group, the steppers accelerate and decelerate to a stop when the target is reached. Then the next target is sent and the process repeats.

This isn't continuous movement, which is what i'm seeking. The example discussion I linked uses a callback to immediately run the onPositionReach() function the moment it finishes instead of stopping.

the StepISR() function's last conditional statement is such:

Code:
else // target reached.
        {
            stpTimer->stop();
            TimerFactory::returnTimer(stpTimer);
            stpTimer = nullptr;
            auto *cur = this;
            while (cur != nullptr) // hack, remove slave motors
            {
                auto *tmp = cur->next;
                cur->next = nullptr;
                cur = tmp;
            }
            isMoving = false;

Instead of stopping, the callback should be invoked to run the onPositionReach() function again without interruption. Does that make sense?
 
I assume you’ve tried “multistepper” part of “accelstepper”?

One of the main reasons for teensystep is to apply acceleration to what multistepper does. If you don’t want acceleration just use multistepper.
Another reason for teensystep is for high speed stepper motors. You can’t get high speed stepper motors without acceleration otherwise you’ll lose steps.
 
I assume you’ve tried “multistepper” part of “accelstepper”?

One of the main reasons for teensystep is to apply acceleration to what multistepper does. If you don’t want acceleration just use multistepper.
Another reason for teensystep is for high speed stepper motors. You can’t get high speed stepper motors without acceleration otherwise you’ll lose steps.
Fair enough. I'll take a look at those libraries then.
 
Back
Top