Pull-down resistor on digital IO pin used as output = LOW level on this pin during power-up, restart,...?

Hello,
I'd like to ask your advice. I need to use an arduino to control a stepper motor driver.
(EM806 Stepper Motor Drive / Controller | Leadshine)

In short, the driver has 6 inputs
ENA +/- (enable)
DIR +/- (direction)
PUL +/- (pulse)

which I would like to control with the outputs of the Arduino NANO (precision clone):
ENA-, DIR-, PUL- directly to the GND of the arduino
ENA+, DIR+, PUL+ directly to the digital outputs of the arduino.

And now a question:
As I read, the digital inputs/outputs of the Arduino are set as inputs by default during power-up, restart,... And if I understand correctly, the driver inputs would take it as if they were at HIGH level at this point.
Sure, I can immediately override settings of the the PINs within setup() (I know that it's possible to use writeDigital LOW before setting the PIN as output, etc), but my concern is the moment before setup() is even called. I need the PINS to be there during arduino start, restart,... for the driver at LOW level.

Is the correct solution to connect the arduino pins directly to the corresponding "+" inputs of the driver, but also connect each of these arduino pins to GND via a pull_down resistor (some 10k)?


(example for ENA+/-)

Thank you very much for confirming this idea....

P.S. this is my first project with arduino...

Normally the pins are set to input, output or input pullup inside setup(). But I guess you can do that in the code before the setup() function's definition. So as soon as the code starts executing the pins will be configured even before setup() is called.

So, instead of this:

void setup() {
pinMode(8, OUTPUT);
digitalWrite(8, HIGH);
}

Do this:

pinMode(8, OUTPUT);
digitalWrite(8, HIGH);

void setup() {
}

And this will guarantee that even during arduino start and arduino restart the ENA+ input of the driver will be always on the LOW level even with this connection? (example for ENA+/- inputs)

You don't need any pull-down resistors. The stepper driver has optocoupler inputs, so the arduino only controls one LED per driver input. is absolutely problem-free, even during the startup / power on of the arduino.

That makes sense, thank you!

Just for completeness: Yes, pull up/down resistors can be used to keep pins at high/low level on Reset.

Nonsense! :roll_eyes:

Care to elaborate?

The only automatic pin I/O configuration occurs during a Reset, where most controllers configure all pins for input.

What else should perform such a configuration, according to what rules?

Yes, but for all practical purposes the pins will be set to the programmed values as soon as the code starts executing. The time difference is just too small to have any effect...

Not if a bootloader or some other firmware starts on Reset.

And you imagine this code will actually be executed?

1 Like

Why not? Here's some partial code of what I'm using to drive my stepper motor:

The library header that I made:

"A4988_DRV8825_lib.h"

// A4988_DRV8825_lib.h

class A4988_DRV8825
{
    public:
        A4988_DRV8825(byte stepPin, byte directionPin)
        {
             pinMode(StepPin, OUTPUT); //Note: pinMode set in constructor
             pinMode(directionPin, OUTPUT);  //Note: pinMode set in constructor

            //Default to CW
           digitalWrite(directionPin, HIGH); //Note direction pin set to HIGH in constructor

           //Default to stop
          digitalWrite(stepPin, LOW); //Note direction pin set to HIGH in constructor
        }

        void SetSpeed(float rpm)
        {
            //Code that sets up the required delay between steps to run the motor
        }

        void Run()
        {
            //Code that runs the motor
        }
}

The actual arduino .ino code

#include "A4988_DRV8825_lib.h"

#define DIR_PIN 7
#define STEP_PIN 13

// Initialize the A4988_DRV8825 object with the above pins:
A4988_DRV8825 objDriver(STEP_PIN, DIR_PIN); //Note that the pinMode for DIR & STEP pins are being done in the constructor and not in setup()

void setup()
{
}

void loop()
{
    objDriver.SetSpeed(45.0f);
    objDriver.Run();
}

This code is tested and working perfectly at the moment. As you can see the pinMode() and digitalWrite() for the STEP and DIR pins are being done in the constructor A4988_DRV8825::A4988_DRV8825() which is being invoked when objDriver is instantiated outside of setup().

If you want I will be happy to share the full code for scrutiny. Rest assured setup() is just the arduino framework function for organising code that will be run only once. Any code outside of setup() such as variable initialisation or pinMode or writes, etc still has to be executed in the order in which its written till execution reaches loop().

The bootloader and other framwork initialization is done before user code. Dunno what happens behind the scene with ESP82 and other big controllers. Not a full Windows boot, but the FreeRTOS version. And nothing at all will happen while somebody is pressing the Reset button.

There is no argument against pull up/down resistors on critical control lines. If it seems to work without such resistors the first user will proof the opposite :frowning:

Right. And any code written before setup(), after setup() and before loop() will be executed in that order. Once loop() is invoked control will not reach any code that is written after loop().

How comes that you assume any order of execution, based on the code position inside a module? Where is a place in the C/C++ syntax that allows for statements outside functions?

You can have global variables, with declaration and initialisation (i.e. defined not just declared). Statements that are executable directly (not function defintion) will be executed as encountered. Functions are callable and will be executed when called. So setup() is indeed the first function to be called by the arduino runtime itself but any code declared and implemented before it that is directly executable will be executed. To the computer its just a set of instructions that it starts executing from the start of the code. The arduino framework or runtime will execute statements before setup() if they are initialising statments, construction statments or even a function call. If setup indeed is first then we would not be able to initialize any variable in this manner but if you see the code I posted it works perfectly well.

That's in contrast to

So if I enter this line at the begin of the sketch
for (;;) {}
the program will never start?

There is no contradiction. Try it and see.

Any infinite loop before loop() will be executed and will never reach loop().

The same to you. There is a contradiction.