# Stepper motor code question

I watched this Youtube video and would like to replicate it:

It's a video that teaches how to drive a bipolar stepper motor with DRV8825. Here's the code I found in the description:

const int stepPin = 2;//only works on this pin right now
const int dirPin = 3;
const int actPin = 4;//not used
const float motorAngle = 1.8;
const float stepSize = 0.03125;//full=1, half=0.5, quarter=0.25, etc...

void stepperRotate(float rotation, float rpm);

void setup() {
// put your setup code here, to run once:
pinMode(stepPin, OUTPUT);
pinMode(dirPin, OUTPUT);
//pinMode(actPin, OUTPUT); hooked to VCC, so no Arduino control
Serial.begin(9600);

}

void loop() {
// put your main code here, to run repeatedly:

// simple rotation forward then backward:
stepperRotate(1, 100);//rotations, RPM
delay(1000);
stepperRotate(-1, 100);//rotations, RPM
delay(1000);

// the acceleration code towards the end of the video:

// for (int i = 200; i <= 500; i = i + 10) {
// stepperRotate(1, i);//rotations, RPM
// }
// stepperRotate(20, 500);//rotations, RPM
// for (int i = 500; i >= 200; i = i - 10) {
// stepperRotate(1, i);//rotations, RPM
// }

}

void stepperRotate(float rotation, float rpm) {
if (rotation > 0) {
digitalWrite(dirPin, HIGH);
}
else {
digitalWrite(dirPin, LOW);
rotation = rotation * -1;
}

// first figure out how many steps in one rotation, so a motor with 1.8deg per step, equals 360/1.8 = 200 steps/rotation
// then if you're doing half step, that will double, so divide by 0.5, gives 400steps per rotation
float stepsPerRotation = (360.00 / motorAngle) / stepSize;

//now we have the steps per rotation, multiply by the rotations for this command to get total steps
float totalSteps = rotation * stepsPerRotation;
//Serial.println(totalSteps); // debug

//tricky part here - what is the ON/OFF time of the step pin to get the desired RPM?
// First, what is the seconds per revolution? then we can figure out seconds per step
// RPM (rotation per minute) needs to be converted to MPR, so 1/RPM, then seconds per rotation is 60seconds/RPM
// that gives us Seconds per Rotation, but how many seconds per step? well, we just divide that by the number of steps per rotation
// so now we're at 60/RPM/stepsPerRotation
// this is seconds, but we're going to use microSeconds, so let's multiply by 1 Million (1E6)
// then, we want a 50% duty cycle, half time ON, half time OFF, so divide this value by 2, then we end up with:
unsigned long stepPeriodmicroSec = ((60.0000 / (rpm * stepsPerRotation)) * 1E6 / 2.0000) - 5;

//what's up with the -5 at the end? well, in the for loop, we have to compensate for the i++ and i<x check, so 5us is subracted to speed it up a little

//Serial.println(stepPeriodmicroSec);

for (unsigned long i = 0; i < totalSteps; i++) {
PORTD |= (1 << 2);
delayMicroseconds(stepPeriodmicroSec);
PORTD &= ~(1 << 2);
delayMicroseconds(stepPeriodmicroSec);
}

}

I'm having a hard time understanding the last portion, the PORTD |= (1 << 2) and PORTD &= ~(1 << 2), how it works and what it does. Googling didn't help.

I'm also wondering what the Serial.begin(9600) does in the setup portion. I don't think I've seen it before and wonder if that's necessary.

Lastly, I want to power the Arduino (Nano), the stepper motor, and the driver from a USB power bank that outputs 5V. This would simplify my design. Is there any concern with my approach?

Thanks

Hi @paulwece
In order:

2. When posting sketch in topic format it, and use </> tags;

3. These instructions do the following: (Simplified explanation).
PORTD |= (1 << 2) and PORTD &= ~(1 << 2).
PORTD |= (1 << 2) . Shift the number 1 to the left 2 bits and write to PORTD.
<< means shitf left
PORTD &= ~(1 << 2). Shift the number 0 to the left 2 bits and write to PORTD.
~ means the inverse of 1 = 0.
Port D bit 2 is pin 2 of the arduino and in the sketch it was used for step;

4. The project author uses Serial.begin(9600) for DEBUG, but it can be removed.

5. I don't recommend using the USB 5V source as a stepper motor consumes a lot of
current and the USB can be damaged.
Also 5V is not a good voltage to move stepper motors.

RV mineirin

The minimum motor supply voltage for a DRV8825 driver is 8.2V. See the data sheet.

Thanks. So to be sure:

PORTD |= (1 << 2) is equivalent to PORTD = PORTD | (1<<2) , and (1<<2) = 00000100. This will make the bit corresponding to pin 2 (for step) HIGH, but leaves the other bits unchanged.

PORTD &= ~(1 << 2) is equivalent to PORTD = PORTD & ~(1<<2) , and ~(1<<2) = 11111011. This will make the bit corresponding to pin 2 (for step) LOW, and leaves the other bits unchanged.

And toggling pin2 high and low is what drives the stepper because it creates a rising edge?

In programming, when you do things like x+=1, you have to initialize a value for x first. He never initialized a value for PORTD before doing the "PORTD |= (1<<2)". I guess the dirPin is set to pin 3 so depending on whether that's HIGH or LOW, it'll determine the initial state of PORTD before the for loop. But for the other pins (like pin 6, which is unused), is it by default 0?

Thanks

Thanks, I'm actually going to use this driver:
https://www.digikey.com/en/products/detail/trinamic-motion-control-gmbh/TMC-SILENTSTEPSTICK/5724190

and this motor:
https://www.sparkfun.com/products/10551

This is talked about by the same guy in this video:

But he mentions it uses the same code as in the video in my original post, and that video description contains the link to the code, which is why I posted it.

On the Sparksfun page, there is a review that mentions the motor can be driven by 3 V even though it's rated for 12V.

As far as the driver is concerned, I hope I can get away with 5V for the motor supply voltage. Technically the minimum is 5.5V, But according to the datasheet:

Does that mean I can get away with 5V? I really tried to make sense of it but that datasheet is a bit above my head. But the driver seems to allow completely silent operation which is appealing to me.

It seems that it can be operated at 5V somehow.
It is shown there that special wiring for this needs to be done.
But the board with the URL you showed is not.
It is desinged for operate from 5.5V~ motor power supplly.

You will need to solder this tiny little bare chip yourself to build the board for 5V only.
Of course you design and make breakout boards yourself.

Thanks. Here's the board I ordered from Digikey:

It seems the datasheet on the page below refers to the IC only, and I got the whole board. So my board will not be able to use 5V for the Motor voltage (I wonder what might happen if I tried?)
https://www.digikey.com/en/products/detail/trinamic-motion-control-gmbh/TMC-SILENTSTEPSTICK/5724190

Can you recommend a simple, reliable boost converter (easy for newbies) that I can boost my 5V supply to something above 5.5V then? (If that's the only way I can use the board).

How's this:
https://www.pololu.com/product/2116

Reason I prefer using a USB power bank is because I got those lip stick ones that are compact enough for my need and allows for easy recharging. My application doesn't require a lot of current so I should be okay on that aspect. Thanks

Probably, a described board will work at 5V, Maybe.
Try it.
Ofcourse, although it is not guaranteed to work...
Also, when using a constant current driver, the higher the motor power supply, the better in the torque.
When using a constant current driver, the rated voltage of the motor is almost irrelevant.

Inductive devices (including motors) can require large currents at start-up.
Boosting with a small DC/DC converter is not recommended...

Can someone tell me the proper connection of the wiring from that driver to the stepper motor?

Here's the wire diagram for the motor:

And I got it at
Small Stepper Motor - ROB-10551 - SparkFun Electronics.

According to document on the driver, the connection should be:

M1A Motor Coil 1
M1B Motor Coil 1
M2A Motor Coil 2
M2B Motor Coil 2

So I think I should connect it as follows:

M1A black
M1B brown
M2A orange
M2B yellow

but can it also be

M1A brown
M1B black
M2A orange
M2B yellow

or

M1A black
M1B brown
M2A yellow
M2B orange

?

What effect will changing the order have?

Thanks

Unless you make the mistake of connecting two coil (Phase A and Phase B) to crossed H bridges, All the connections you show work fine.

Every time one phase of wiring is replaced, the direction of rotation of the motor is reversed.
However, it is rare that the wiring is completely specified because it is usually easy to change with software.

After talking with the vender, I was told that it must be 5.5V applied to the Motor Supply Voltage (VM). I still use a common power source, so I'm thinking about using a 9V battery. I believe I can power pretty much any flavor of the Arduino with a 9V (I got the Nano). But does this produce a lot of heat? I believe the voltage regulator on the Arduino will just "waste" the extra voltage. But then again, this might not be an issue from a power drain perspective since the microcontroller will use much less power than the motor right?

If you are thinking about smoke alarm batteries, please reconsider. Those batteries, although they are 9V, lack current capacity. They will not run your motor for long, if at all. Those batteries may run a Nano, by itself, for a little while, but are less than ideal power source and useless for motors.

I ended up using 4 AA batteries to power the motor, and used a boost converter to apply a Motor Voltage of 12V. When the motor was running it was drawing 2A at maximum, that's way higher than expected.

The boost converter and motor was getting hot after only a short operation. The higher the boosted voltage to the motor, the higher the current draw from the battery side right?

I found that boosting the voltage really made the motor silent for some reason. Anyone know why?

I also wonder if increasing the rpm of the motor will make it run even hotter? Will it lead to an increased current consumption?

The driver you got is constant current control driver.
The current supplied to the motor be the value setting yourself, did you set the current to match the rated current of the motor?

Also, if the stepping motor has a constant voltage, it consumes the most current when it is stopped.
However, the driver your using has a constant current, so if you set it properly, it will always try to supply that current regardless of the rpm.
(The driver may be smart and have a quiescent current reduction function. This may also need to be setting.)

Thanks for reminding me. From the motor spec I posted in a previous post, it seems the rated current is 400mA. Could this be understood as the maximum current?

https://learn.watterott.com/silentstepstick/faq/

I should set the potentiometer such that Vref is 0.39 V (based on the calculator they provided, where

Vref = (Irms * 2.5V) / 1.77A = Irms * 1.41 = Imax

So if Imax is 0.4A, then I get Vref of 0.39V. Is that correct?

I'm impressed by how quiet the stepper is when using this driver. My application requires very little torque (but I do need at least 100 rpm of speed). I hope to cut down on power consumption and heat by decreasing torque while still maintaining the quiet operation and speed. Would setting the current lower achieve this?

Thanks

Yes.
That driver boards has current detection resistor attached 110mΩ.
As a result of the datasheets formula, the voltage of VREF is almost equal to the maximum motor current.
That is, VREF = 0.4V means that the maximum motor current is 0.4A.

The motor spec says 400mA, you should test with that current and actually run the motor to check it you can touch.
If it is overheated to where you cannot keep touching it, there is too much current.
Adjust the current so that the required torque and rpm can be achieved while checking the heat generation.
If it cannot be obtained even if the current is increased enough to overheat, start over from the motor selection.

The TMC's stepper driver is fantastic and I have adopted TMC2209 as the motor driver for my DIY 3D printer.

Also, if the constant current driver is used correctly, the rated voltage of the motor can be read as "the lowest supply voltage".
(It's explained earlier.)
If you are using an adjustable boost converter, you may be able to get a higher rpm with the same power by boosting to 24V etc.
Be careful about the maximum voltage of the motor driver.
This is complicatedly related to the inductance of the motor, etc., and it is troublesome, so explanation is omitted.

Thanks, when I measure Vref (for setting current), I'm supposed to have power connected to VM, and 5V to VIO right?

The way I understand is that the driver will drive the motor with a sinusoidal current, with the I_rms determined by my current setting. I determine the current setting based on the rated current of the motor. The rated current of the motor is just the maximum current that the motor can handle. The rated voltage of the motor is just the rated current multiplied by resistance of the coils.

There is nothing stopping me from setting the current (for the driver) lower than the rated current of the motor, in which case I'd get less torque. If I set the current too high but supply insufficient voltage to VM, the current sinusoid might get "clipped" which increases noise. Setting the current lower shouldn't affect the speed I can get out of the motor (which still keeping things quiet).

Please correct me if I misunderstood any of the above.
Thanks