2

I am at the moment trying to make a bipolar stepper motor move. I am interfacing it through a control board, which takes the input Step, Dir, En, and 5V.

I am providing those input signal via an Arduino, but can't get the damn thing to move. all it does it move a step forward and backwards, like it being stuck or and tries to wiggle out of something.. What could the reason be..

Here is the Code:

#include "stepper_motor.h"
int max_step = 200;
stepper_motor::stepper_motor()
{
  pinMode(BUILTIN_LED,OUTPUT);
  pinMode(step_pin,OUTPUT);
  pinMode(dir_pin,OUTPUT);
  pinMode(en_pin,OUTPUT);

  alive_bool = true;
  position_bool = false;
  step_count = 0;
}

void stepper_motor::step_pwm()
{

  if(position_bool==true)
  {
    //Dir pin low 
    digitalWrite(step_pin, LOW);
    digitalWrite(dir_pin,LOW);
    digitalWrite(en_pin,LOW);

    delay(0.005);

    digitalWrite(step_pin, LOW);
    digitalWrite(dir_pin,LOW);
    digitalWrite(en_pin,HIGH);

    delay(0.005);

    int step = 0;
    while(step < max_step)
    {
      digitalWrite(step_pin,HIGH);
      delay(1);
      digitalWrite(step_pin,LOW);
      delay(1);
    }

    //digitalWrite(en_pin,LOW);
    //position_bool = false;
  }
  else
  {
    //Dir pin high 
    delay(1000);
    digitalWrite(step_pin, LOW);
    digitalWrite(dir_pin,LOW);
    digitalWrite(en_pin,LOW);

    delay(0.005);

    digitalWrite(step_pin, LOW);
    digitalWrite(dir_pin,LOW);
    digitalWrite(en_pin,HIGH);

    delay(0.005);

    digitalWrite(step_pin, LOW);
    digitalWrite(dir_pin,HIGH);
    digitalWrite(en_pin,HIGH);

    int step = 0;
    while(step < max_step)
    {
      digitalWrite(step_pin,HIGH);
      delay(1);
      digitalWrite(step_pin,LOW);
      delay(1);
    }

    //digitalWrite(en_pin,LOW);
    //position_bool = true;
  }



}

Updated step_pwm():

void stepper_motor::step_pwm()
{
    //Start -  En Low , DIR HIGH, STEP high
    //init configuration!
    digitalWrite(step_pin, HIGH);
    digitalWrite(dir_pin,HIGH);
    digitalWrite(en_pin,LOW); // Previous LOW

    delay(0.005);

    //T1-  En HIGH , DIR HIGH, STEP HIGH
    //Enable high
    //digitalWrite(step_pin, HIGH);
    //digitalWrite(dir_pin,HIGH);
    digitalWrite(en_pin,HIGH);

    delay(0.005);

    //T2-  En HIGH , DIR low, STEP HIGH
    //Direction choosen
    //digitalWrite(step_pin, HIGH);
    digitalWrite(dir_pin,LOW);
    //digitalWrite(en_pin,HIGH);

    delay(0.005);
    //T2-  En HIGH , DIR low, STEP HIGH
    //STEP  step between low and high with 2.5µs between

    while(1)
    {
      digitalWrite(step_pin,LOW);
      delay(2.5);
      digitalWrite(step_pin,HIGH);
      delay(2.5);
    }

}

The control board i am using is a ST330-v3 The motor i am using is this one here is a little block diagram of how things are connected.

enter image description here

18
  • Your voltage is too low. Sep 24, 2016 at 8:08
  • 1
    So... you suggesting connect the negative terminal of the power with ground terminal of the arduino? Sorry for asking such a stupid question.. I am very much a noob when it comes to electronics.. Not at all my strong suit.. Sep 24, 2016 at 13:08
  • 1
    Verify continuity in the two motor coils (multimeter). Reconnect and replace the Arduino with a debounced pushbutton driving the step input and tie EN and DIR to active and an arbitrary level respectively. Verify the voltages change across the coils sequentially. Sep 24, 2016 at 13:38
  • 1
    Maybe your impression of which pin is enable and which is direction is swapped. Best recheck everything with the most authoritative source documentation. If the board documentation isn't great, get the IC data sheet and trace the connections to it. Sep 24, 2016 at 15:55
  • 2
    But the d1 mini uses an ESP8266 which has 3.3V GPIO. You are powering the opto-couplers with +5V and the ESP8266 is pulling down from +3.3V to its ground, so the optocouplers are getting 1.7V (5V-3.3V) when the GPIO outputs are high. Since the infrared LED in the optocoupler only needs 1.1V to turn on, there is a chance it will stay turned on enough to prevent the high signal from being transferred. This might explain why you had to disconnect the EN signal (yes, disconnected is same as high on the ST330 - bad design!)
    – Bruce Abbott
    Sep 24, 2016 at 17:00

2 Answers 2

2

You must set EN BEFORE you set DIR. The datasheet says EN must be high for at least 5 microseconds before you set DIR. You should probably just set EN high when your program starts, then not fool with it until your program ends.

The next thing is that I don't see you incrementing the variable "step" anywhere. So, if you did get the stepper to turn, it wouldn't stop.


The updated code looks like it ought to work.

You should use DelayMicroseconds instead of Delay(0.005) though. Delay takes an integer instead of a decimal value, so you won't get what you expect. Curse the Arduino IDE for not throwing a fit when pass a float for an int.


It looks like anything working properly is purely luck. The board you are using(NOT an Arduino) uses 3.3V logic levels. The ST330 says a high must be at least 4V, so if it reacts to your control signals at all it is just luck.

The 8266 outputs are rated for 12mA, the ST330 inputs need about 20mA, so you are over doing it. The 8266 might put up with, and might just die on you.

You might be able to drive the ST330 by switching the mode of the pins.

Low would be "set pin to mode output and set low."

A high would be "set mode input."

Input mode leaves the pin floating, which the ST330 will interpret as a high.

Other than that, you could use NPN transistors to drive the ST330 inputs, then invert your output signals.

The NPN would invert your signal (a high becomes a low) so you would have to set an output to low to get a high going into the ST330.


You can use NPN transistors like this to drive the ST330:

schematic

simulate this circuit – Schematic created using CircuitLab

Setting the GPIO from the ESP8266 to high would cause a low on the ST330 input.

Setting the GPIO pin to low would cause a high on the ST330 input.

This is the solution I would prefer if I needed to use the ESP8266 with the ST330.


If you'd like to try a purely software solution, then do this:

  1. To send a low to the ST330 input, set the GPIO to pin mode output and set the output to low. (pinMode(step_pin,INPUT) then DigitalWrite(step_pin,LOW))
  2. To send a high to the ST330 input, set the pin mode to INPUT (pinMode(step_pin,INPUT)

When the GPIO pin is in input mode, it floats. It doesn't have a voltage level of its own - it acts like it is disconnected.

If that works, I'd still prefer to use the transistors.


You can avoid all of this using the UNO. It has 5V logic levels on the outputs.

16
  • It this based on the updated code or the prior? Sep 24, 2016 at 13:49
  • The step variable is missing that is right, and it turned yes it didn't stop. but the direction cannot be coded. what the mean by EN set before DIR is set.. isn't the case? Sep 24, 2016 at 13:55
  • The ST330 has opto-couplers that require connection to +5V and signal inputs only ('yin and yang' interface!). To maintain the isolation barrier the Arduino ground and ST330 ground should not be connected together.
    – Bruce Abbott
    Sep 24, 2016 at 16:21
  • @BruceAbbott: I missed that while looking at the timing diagrams. I'll change that part.
    – JRE
    Sep 24, 2016 at 16:25
  • @CarltonBanks: Based on the original code. I'll take a look at what you've changed.
    – JRE
    Sep 24, 2016 at 16:27
0

This is problematic:

 delay(0.005);

The Arduino delay() function takes an unsigned long as an input, which is an integer rather than floating point type. As a result, the argument you pass to it will be treated as zero. Depending on how delay() is implemented this will result in either no delay (beyond overhead), or a minimum that may be longer than you intended.

Of course you now seem to only be running this code once, and then going into an unending loop which uses a 2.5 ms delay that will, for the same reason, be more of a 2ms delay.

3
  • I am not sure i understand the answer.. I myself have wonderes why it works with the delay() and not delayMicroseconds() it seems a bit of. Sep 24, 2016 at 16:47
  • 1
    You need to take time to understand the difference between integer and floating point types, otherwise any success will be little more than luck. Sep 24, 2016 at 17:10
  • Ohh.. i understand the difference.. The only reason why i know it works is as you mention yourself. The code overhead. running delay(0) or delay(0.005) takes aprox. 12 µs which would have fulfilled the minimum required timeslot. Sep 24, 2016 at 17:15

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.