Teensy 3.6 - Interface a Microstep driver which uses 5V

Status
Not open for further replies.
Thanks a lot for the valuable input. I'll prepare a few examples and add them to the repo.
 
@Ed Clark -- Just curious, which drivers are you using and for what size motors?

--Jon

Jon,

My stepper setup is about as cheap as you can go.

Drivers:
https://www.amazon.com/gp/product/B016ZJS1FA/ref=oh_aui_detailpage_o03_s00?ie=UTF8&psc=1

Stepper Motors:
https://www.amazon.com/gp/product/B01H1B1H6Q/ref=oh_aui_detailpage_o05_s00?ie=UTF8&psc=1

driven by a cheap 24v 10 amp switching supply.

I started with the a dual DRV8825 Arduino shield. But I had problems with getting the current limiting set properly. So I had problems with some of the runs on the shield opening up. Then moved to teensy and just jumped to the larger external drivers. They handle the heat 1000x better. Especially if you leave the steppers enabled all of the time.

Maybe my ignorance is bliss. But when I switched to these drivers with the teensy I didn't think much about the teensy output levels. Specs on 5v TTL should be anything over 2.0 volts as a high. I didn't figure 3.3v would be an issue. I put it together, it worked and I moved on and forgot about it until I saw this thread.

I have put an o'scope on my driver input pins many times and always see 3.3v peak. If those voltages were sagging under use I'm not sure I would blame the levels. Normally that would indicate a much lower impedance than expected or a source V+ issue somewhere. I have had plenty of problems with USB cable quality and voltages as well as the same problems with USB hubs. Get a good quality USB cable and POWERED USB hub and your V+ shouldn't be a problem. Or power externally with a more capable supply/regulator. But I admit I'm no expert. This is just my experience.

I also don't use any libraries for the drivers. Because I'm using absolute position encoding in my project I found it easier to position the motors by controlling the Stepper signals manually. Yes, I turn the control pins on and off manually. Looping a highly microstepped motors position based on a couple analog inputs is exactly why I started using a Teensy.

Hope this was helpful.

Thanks,

Ed
 
@luni -- I look forward to your examples, and my smooth transition. :rolleyes:

@Ed -- Yes Ed, that's very helpful. I may buy one or two of the TB6600's just to see how they work. It would be good to find a simple, reliable external driver that worked with the 3.3V straight out of the Teensy's. Sounds like you found one.

I'm no electronics wizard as I said earlier, and I've wondered why the majority of the inexpensive import external drivers like these, seem to have optocouplers that want higher than 3.3V.

--Jon
 
Yes, this:

Variable speed set using Paul's encoder library (this was a challenge for me personally, so I know how hard it can be, e.g. increase / decrease speed based on knob rotation, extra credit for bumping up the speed increment if knob is rotated faster ;-)

and this:

Serial communication - this is the main area that causes huge problems in Accelstepper performance due to architectural delays. Serial output for anything from debug (println), to getting keyboard input. I don't know what user expectations are for serial usage while moving motors, but there are lots of questions that arise (and performance limitations especially using an Uno and motors, which TeensyStep circumvents for the most part)

...would be very interesting also for me.

If you describe what information / examples would be useful for you (and probably others) I can add a few chapters to the readme.

I have also another suggestion as it's not easy (at least for me) to implement automatic forth and back movements as required in many winding applications, for example as shown in my video: one motor runs while the other turns back and forth. There is a product called PTHAT which basically is a controller board for 4 steppers: one of the serial commands it accepts is called Set Auto Direction Change and does exactly what is needed for coil winders. But in my video I run the motors without any acceleration / deceleration otherwise I can't calculate the moment when to change direction: it would be great to enable acceleration / deceleration also in winding applications.
 
I'll be curious to see luni's reply, but your winding application is exactly what his library does perfectly...

1) Define the travel + and - for the width of a wrap (shuttle travel)

2) Decide how many turns are needed for the traverse (say n turns * # of microsteps per revolution for your motor)

3) Then just run from + to - in n turns, using one of his controllers and a move command,

4) Then swap and go from - to + in n turns again,

5) Repeat until your code determines what is full for your spool.

The library will handle the accelerations and decelerations while the shuttle oscillates back and forth.

I am doing the identical thing (but not for winding) in my application, but using Accelstepper. Moving to luni's TeensyStep will eliminate about 1/2 of my code.

--Jon
 
I have also another suggestion as it's not easy (at least for me) to implement automatic forth and back movements as required in many winding applications, for example as shown in my video: one motor runs while the other turns back and forth. There is a product called PTHAT which basically is a controller board for 4 steppers: one of the serial commands it accepts is called Set Auto Direction Change and does exactly what is needed for coil winders. But in my video I run the motors without any acceleration / deceleration otherwise I can't calculate the moment when to change direction: it would be great to enable acceleration / deceleration also in winding applications.

Hi Jun,

how would that work exactly? Maybe I'm completely wrong, but in my understanding, if you want to decelerate the linear motor at the end of one layer, you also need to decelerate the rotation motor at the end of the layer to avoid a bad winding. -> Wouldn't that be a simple synchronized movement of both motors? I.e. if the linear motor needs say 10000 steps to reach the end of the layer you can easily calculate the required steps for the rotation motor out of the geometry of the winder. Say the calculation gives 50000 steps. You'd then simply set the relative targets of both motors respectively and start the synchronized movement. After the movement is done you'd set the relative target of the linear motor to -10000 and the relative target of the rotation motor again to 50000. and start the movement....

Or am I missing something?

Lutz

---
Edit: Jon was faster :)
 
Last edited:
- Variable speed set using Paul's encoder library (this was a challenge for me personally, so I know how hard it can be, e.g. increase / decrease speed based on knob rotation, extra credit for bumping up the speed increment if knob is rotated faster ;-)
- Variable speed reading a pot on an analog pin (lots of beginners have issues with reading a pin occasionally, rather than every pass through loop(), simple interrupt based example would be fine too, but must be complete and commented)

I assume this is supposed to change the speed on the fly like a jog dial on a cnc? I.e. changing the speed of a synchronized movement should change the speed of all the motors such that they stay synchronized, correct? This might be an interesting feature which is not implemented currently. I'll try to find a solution for that
 
I assume this is supposed to change the speed on the fly like a jog dial on a cnc? I.e. changing the speed of a synchronized movement should change the speed of all the motors such that they stay synchronized, correct? This might be an interesting feature which is not implemented currently. I'll try to find a solution for that

Yes, but I'm not sure which part you're asking about...

For general speed change I guess I'd say more like "Feed Override" on a CNC machine, where the axis / axes would speed up, while already in motion. I start a motor (run / stop button), then use the encoder knob to adjust speed dynamically (up to max of course). With multiple motors, generally the slower motor determines the speed for all.

The other part of the question, yes, what I was doing was trying to make a software "range multiplier" equivalent to a jog dial in a CNC, but instead of manually selecting the range multiplier, I adjusted the multiplier based on speed of the knob rotation.

In my code I wrote a simple detection, if the knob was rotated faster than x counts in n millis (or micros?), I just increased the speed multiplier increment. E.g. instead of incrementing by say 10 per click, I incremented by 50 per click, or 100 per click. Otherwise the increase / decrease in speed was just the lower value multiplier, like 10 per click.

The idea worked well, but had to be tweaked for each encoder I used in various versions. But it was a neat solution to an "old world" problem.

--Jon
 
I'll be curious to see luni's reply, but your winding application is exactly what his library does perfectly...

if you want to decelerate the linear motor at the end of one layer, you also need to decelerate the rotation motor at the end of the layer to avoid a bad winding.

Exactly! But because the filaments I wind are extremely thin and soft I don't want to decelerate the rotation motor at the end of each layer as this increases danger of filament breaks. Also the speed of the linear motor is slow and thus could change direction even without acceleration / deceleration. Initial acceleration of the rotation motor at the very beginning of the winding process is important though, because a sudden start of rotation will always break the filaments. So a "toggle dir pin after every x steps until target steps are completed"-command (similar to the mentioned command of the PTHAT) would be useful for winding applications.
 
EDIT (well, no edit since I can't edit my above post anymore...):

I just saw that there is a feature reguest which probably would cover my situation when a "toggle dir pin after every x steps" is required (I could do it as epicycloid suggested and use the call back to start the next winding layer).

But in general I still think it would be useful to issue commands during motors already running, so change dir as I suggested, and also change speed as suggested by epicycloid:

Variable speed ... simple interrupt based example would be fine

This would users enable to start motors and change the relation between their speeds or change the speed for the motors on the fly like in PTHATs Change-Axis-Speed on-the-fly-command while keeping all together started motors synchronised including final deceleration.
 
Would something simple like this not work?

Code:
#include "Arduino.h"
#include "StepControl.h"

Stepper linMotor(1, 2);
Stepper rotMotor(2, 3);

StepControl<> RotationCtrl;
StepControl<> LinearCtrl;

void setup()
{
    rotMotor
        .setMaxSpeed(10000)
        .setAcceleration(50000);

    linMotor
        .setMaxSpeed(5000)
        .setAcceleration(500000); 

    int linSteps = 56400;  // number of steps per layer (linear motor)
    int rotSteps = 121000; // number of steps per layer (rotational motor)
    int nrOfLayers = 5;
    
    rotMotor.setTargetRel(rotSteps * nrOfLayers);
    RotationCtrl.moveAsync(rotMotor);

    for (int i = 0; i < nrOfLayers; i++)
    {
        linMotor.setTargetRel(linSteps);
        LinearCtrl.move(linMotor);
        linSteps = -linSteps;
    }
}

void loop()
{
}
 
Last edited:
Would something simple like this not work?

Many thanks for your code! I just run it on my machine. I guess I did not describe the problem well enough... Let me try again. Here is a graph of what the motors do:

ramps.jpg

linMotor carries out the same amount of travel for each layer. But rotMotor runs a different number of steps during each layer: section a, b, c, d and e should have the same number of steps, but section a and e contain less steps than section b, c and d.

How can this be solved?
 
You are right of course, so you could do the obvious and adjust the steps for the first and last layer but that is somehow ugly and will lead to a not constant pitch during the acceleration / deceleration of the motors. Since you do not want to stop the rotation motor during layer changes you necessarily need to hard switch the direction of the linear motor at a layer change to keep the constant pitch. If this is (as you wrote) not a problem you can easily mimic that AutoDirectionChange command you mentioned above:

Since the controller sets the direction pin only at the beginning of the movement you will not interfere with any internal logic if you simply switch the pin by external code whenever you want.

Code:
#include "Arduino.h"
#include "StepControl.h"

constexpr int pinLinStp = 0;
constexpr int pinLinDir = 1;
constexpr int pinRotStp = 2;
constexpr int pinRotDir = 3;

Stepper linMotor(pinLinStp, pinLinDir);
Stepper rotMotor(pinRotStp, pinRotDir);

StepControl<> controller;


void setup()
{
    rotMotor
        .setMaxSpeed(10000)
        .setAcceleration(50000);

    linMotor
        .setMaxSpeed(10000)
        .setAcceleration(50000);
 

    const int linSteps = 100;  // number of steps per layer (linear motor)
    const int rotSteps = 100;  // number of steps per layer (rotational motor)
    const int nrOfLayers = 5;
    
    int oldDir = -1;           // stores the current direction of the motor
    
    linMotor.setTargetRel(linSteps * nrOfLayers);  
    rotMotor.setTargetRel(rotSteps * nrOfLayers);    
    controller.moveAsync(rotMotor, linMotor);    //we want both motors run in sync 

    while (controller.isRunning())  
    {
        int dir = (linMotor.getPosition() / linSteps) % 2; 
        if (oldDir != dir)  // check if one layer is complete... and switch motor direction after the layer
        {
            oldDir = dir;
            delayMicroseconds(10);   // need to wait a bit to avoid switching during a step pulse
            digitalWriteFast(pinLinDir, dir);
        }
    }
}

void loop()
{
}

Total picture. The included measurements (right side of the blue labels) show the number of step pulses. I chose rather slow acceleration to demonstrate that the switch works correctly even while the rotation motor is still accelerating.

mot1.PNG

Zoomed in at a direction change

mot2.PNG



Hope that helps
 
Last edited:
@luni -- Brilliantly elegant solution to a very specialized problem. I hope that helps jpk sort out his issue.

Even if it doesn't it applies to my very similar problem, and is a clever and insightful approach that would never have occurred to me.

Thank you.

@Theremingenieur, jpk & luni -- Thank you all for the level shifting schematic help too. I got all that working on the bench yesterday. The DM542T driver I'm experimenting with at the moment is very nice, and much, much smoother than the DRV8825's I had been using (for my smaller size motors). This opens up a lot of new possibilities.

--Jon
 
Last edited:
...to hard switch the direction of the linear motor at a layer change to keep the constant pitch. If this is (as you wrote) not a problem you can easily mimic that AutoDirectionChange command you mentioned above

Many thanks again for your help. I run the code on my machine and it worked fine even if the motors have to carry out different numbers of steps per layer!

I also tried to change speed on the fly:

Code:
#include <StepControl.h>

Stepper motor(11, 5);

StepControl<> controller;

void setup() {
  motor
  .setAcceleration(5000)
  .setMaxSpeed(7000);               // set speed
  controller.rotateAsync(motor);

  delay(2000);

  motor
  .setPullInSpeed(7000)             // set current speed as new pull in speed
  .setMaxSpeed(14000);              // set new speed
  controller.rotateAsync(motor);

  delay(2000);

  controller.stop();
}

void loop() {}

If the new speed is higher it works, but I can't get it to decelerate properly. I tried to re-set pull-in speed every time I changed speed but did not succeed...
 
3) Serial communication - this is the main area that causes huge problems in Accelstepper performance due to architectural delays. Serial output for anything from debug (println), to getting keyboard input. I don't know what user expectations are for serial usage while moving motors, but there are lots of questions that arise (and performance limitations especially using an Uno and motors, which TeensyStep circumvents for the most part).

I just uploaded a simple example to github showing how to use the serial interface while a motor moves in the background. https://github.com/luni64/TeensyStep/tree/master/examples/Interfacing

Just use TyCommander or SerMon or any other serial terminal to send the following commands to the teensy

m -> starts a movement of 20000 steps
s -> stops the movement
e -> does an emergency stop

To demonstrate output to the serial port while a motor moves I simply send the current motor position the port.

serial.PNG
 
... I also tried to change speed on the fly .... If the new speed is higher it works, but I can't get it to decelerate properly. I tried to re-set pull-in speed every time I changed speed but did not succeed...

That won't work. The library pre calculates the motion parameters when the move starts. Changing those parameter on the fly is currently not possible (I'm working on it, but this will take some time)
 
Apologies for resurrecting this thread, but I am diving back into my stepper projects and the comments and information on this thread have been helpful.

@luni -- I see on your grbl board posted here that you don't tie the unused 74HCT245 pins to Vcc or GND. In looking at datasheets, the older TI data sheets say to do this with unused pins, while newer datasheets don't seem to mention it as a requirement. Has something changed and this doesn't matter anymore (or at our speeds / frequencies)?

--Jon
 
You are right, it is always a good idea to tie unused inputs to gnd. The board was just a quick test board it worked OK without the gnd connections but I don't recommend that.
 
Thanks luni. I was worried that our board designs were overkill, with resistors for all the possible unused driver connections out of the 74HCT245's.

A friend and I have worked on two somewhat generic Teensy / multi-driver boards, one for a T3.2 and two drivers, the other for a T3.5 and 4 drivers. While they were designed specifically for our project, they are quite generic, including bringing out most pins, and extra breadboard space.

We wanted them to work with anything from low current NEMA 17's, up to bigger motors and drivers (6A limit). So they were both designed to be used with any combination of DRV8825's, Panucatt's Bigfoot BSD109A's (up to 3A), or external "industrial style" drivers like the DMT542's I've been using most recently. The Bigfoot's and the external drivers seem to need 5V, hence the 74HCT245's and all the earlier discussion in this thread.

If it wasn't for this thread, and all the help and comments, I think I'd still be stuck at the bench trying to get the more complicated variants moving. Thanks to everyone who added anything to the conversation!

--Jon
 
Yes, as .pdf's attached. You probably can't open the KiCad files, and it didn't like them for uploads anyway.:confused:

--Jon
 

Attachments

  • RoseEngine2_T32.pdf
    319.8 KB · Views: 114
  • RoseEngine4_T35.pdf
    564.3 KB · Views: 132
Status
Not open for further replies.
Back
Top