Stepper step/dir drive node


#1

Hi, folks!

I see some people are trying to adopt the square-wave node to drive stepper motors and fail. It is because the *-wave nodes are LFO (low-frequency oscillators) and can’t give more than a few dozen hertz. A hardware timer is required to produce a higher frequency. Here’s my simplistic attempt to control a motor with step/dir interface:

https://xod.io/libs/nkrkv/stepdir/

Here’s a demo:

P.S> If you are looking for a node to drive an unipolar stepper connected through ULN200x, take a look at https://xod.io/libs/txgruppi/stepper-28byj48/

P.P.S> I created a channel for quick & dirty XOD videos with poor video quality and awful voice acting. Subscribe to be notified about new videos :wink:


Maximum square wave pulse frequency
#2

Thanks for this stepper library. I was up and running quickly with my stepper test, which worked fine. However, when I try this library with two steppers, I realized it’s not so simple to get two steppers moving at the same time. When I try and trigger two steppers to move at the same time, the second stepper won’t accept input to move until the first stepper is done moving.

Here’s a simple description of my test patch. 1 stepper and a button that makes the stepper move 500 steps forward. Another stepper and a button that makes it move 500 steps forward. If I press the first button, the stepper starts moving. If I keep pressing the second button, nothing happens while the first stepper is still moving. Once the first stepper stops moving, the second and button and stepper work fine, but will also block the first button from operating the first stepper.

Any hints on how to make multiple steppers work together?? My project will require joystick control of steppers, which seems pretty simple but with this roadblock, I’m not sure how to proceed.


#3

Ok, I’ve dug a little deeper into this. I looked at the C++ code and it looks like this library is using the tone() function to move the stepper motors. I looked at the documentation for tone() and it doesn’t look promising.
Here’s the doc:
https://www.arduino.cc/reference/en/language/functions/advanced-io/tone/
On that page it says:

Only one tone can be generated at a time. If a tone is already playing on a different pin, the call to tone() will have no effect. If the tone is playing on the same pin, the call will set its frequency.

Use of the `tone()` function will interfere with PWM output on pins 3 and 11 (on boards other than the Mega).

It is not possible to generate tones lower than 31Hz

This isn’t looking promising. It looks like if a call to tone() with a specified duration has not yet finished, all subsequent calls to tone() will be ignored. Even worse, it looks like calling tone() will messup the PWM output on pins 3 ad 11. And finally, slow stepper speeds can’t be done since tone() can’t be used to generate square waves slower than 31Hz.

Am I understanding all of this correctly? Is there a better way to control multiple stepper motors that need to perform moves at the same time?


#4

If you are willing to buy more hardware, like a driver board, aka H-Bridge. Drivers have several advantages:

  • They handle the current
  • They have nice logic, so you might be able to micro-step
  • They can handle forward/reverse
  • They don’t take any low-level timing on the Arduino: just set high/low (till done). So, multiple drivers run “independently”.

#5

I do have very fine A4988 stepper driver boards. I can control multiple steppers moving independently and simultaneously if I write C++ code. That wasn’t the point of the post though. The point of the post was how to do it with XOD, since the stepper node in this thread doesn’t seem to be able to control multiple steppers moving at the same time.


#6

Yes, I misunderstood.


#7

Yes, gentlemen, you’re right. This is a very simple library which depends on the tone and—as a consequence—on the number of spare hardware MCU timers.

But can we actually control more steppers at once? Someone has to generate a precise and correct pulse train for the driver. If I’d had such task, I’d either take a more powerful MCU (more timers) or a smarter driver which can generate the pulses on its own.

Another possible solution is to emulate several channels in software. Depending on performance requirements it can interfere with other MCU tasks and interrupts which leads to glitches in motors behavior. But…

That’s sounds promising. Would you share a link to the library or code snippet you’re using to deal with it?


#8

I suppose I could share some code that I’ve been testing my Steppers with but honestly, It would be pretty trivial. I’m new to Arduino but I’ve been working on multiple projects with steppers for decades. The preferred way I’ve found so far with Arduino is to use the AccelStepper library. It’s probably the most similar way to programming steppers that I did with Java years ago. It’s straightforward in that:

  • Each stepper gets an instantiation of the Stepper class
  • Each stepper starts at position 0 when the program starts, any stepper can have it’s current position reset as zero any time during running the program with a method call, or setting a property on the object.
  • The class keeps track of the current motor position. With each call to move the stepper, the position is updated continuously as the stepper makes it way toward the target position.
  • The class allows easy control of multiple steppers by setting a target position for the stepper in absolute value (go to position 365778) or in relative value (move forward or backward 27558 steps).
  • Once a target position is assigned to ANY stepper, within loop() a few things happen:
    – The run() method is called in loop() for EVERY stepper
    – The run() method compares stepper.targetPosition() to stepper.currentPosition() to decide whether or not the stepper should get some pulses to step it or do nothing.
    – Naturally, the decision to step the motor in each loop() also considers the direction the motor should be moving (forward or backward) and sets the direction pin to the controller high or low.

That’s pretty much it. Simplified I know but using this type of library makes it dead simple to take input from any control, physical or in software, GUI, webpage, etc. The input sets the target position of each stepper. The stepper.run() method in loop() decides whether the stepper needs to step to get where it needs to be and so on.

Hopefully that made sense.