Stepper reverses direction intermittently

I have a project that opens a window blind in the day and closes it at night. It worked great for a week or two until we had a power outage. That night the blind tried to open, and in the morning it tried to close. Seems like the rotation reversed. I dealt with it by reversing two of the stepper wires. But since then it seems to reverse direction intermittently unexpectedly. I don't mean it reverses while turning, but that at dusk sometimes it tries to open when it should close and vice versa.

It uses a Trinket 5V, an SN754410E H-bridge, and a NEMA 17 motor (pretty sure but no markings).

// WARNING! If the motor is too strong this program can damage your blind.
// Customize these params according to your board. Make sure your PHOTO_PIN supports analog in and that 
// you use the analog pin number, not the board pin number.
#define PHOTO_PIN 1 //  Analog pin 1 = PB2 on the trinket
#define A1_PIN 1
#define A2_PIN 0
#define B1_PIN 3
#define B2_PIN 4
#define ANALOG_BITS 10
#define ANALOG_MAX ((1 << ANALOG_BITS) - 1)

// You may need to reduce AVG_HEAD if the motor starts at the wrong time of day
#define AVG_HEAD 0.5  // Weight of the latest sample 
#define AVG_TAIL (1.0 - AVG_HEAD)

// Reduce DAYLIGHT for day to start earlier / end later. Increase DAYLIGHT_MARGIN if the blind reverses
// immediately after it opens / closes.
#define DAYLIGHT 0.5
#define DAYLIGHT_MARGIN 0.02

// Customize these params according to your motor.
#define STEPS 200
#define RPM 100

// Customize this param according to your blind.
#define TURNS -5     // Turns at sunset

Stepper stepper = Stepper(STEPS, A1_PIN, A2_PIN, B1_PIN, B2_PIN);
bool isOpen = false;  // Make sure your blind is in this position when booting.
float avgLight = isOpen ? 1.0 : 0.0;

// Return the lightness value calculated with exponential moving average.
float sample() {
  float floatRead = ((float) analogRead(PHOTO_PIN)) / ANALOG_MAX;
  avgLight = (avgLight * AVG_TAIL) + (floatRead * AVG_HEAD);
  return avgLight;
}

void setup() {
  // These may or may not be strictly necessary
  pinMode(A1_PIN, OUTPUT);
  pinMode(A2_PIN, OUTPUT);
  pinMode(B1_PIN, OUTPUT);
  pinMode(B2_PIN, OUTPUT);
  pinMode(PHOTO_PIN, INPUT);  // or INPUT_PULLUP if you do not have a pullup resistor in place  

  stepper.setSpeed(RPM);
  
  delay(1);
}

void turn(int rotations) {
  stepper.step(rotations * STEPS);

  // Turn off the current because the stepper doesn't need to hold in place.
  digitalWrite(A1_PIN, 0);
  digitalWrite(A2_PIN, 0);
  digitalWrite(B1_PIN, 0);
  digitalWrite(B2_PIN, 0);
}

void loop() {
  float s = sample();
  if (isOpen && s < DAYLIGHT - DAYLIGHT_MARGIN) {   // Sunset happens
    turn(TURNS);                            // Assuming positive rotations to close 
    isOpen = false;
  } else if (!isOpen && s > DAYLIGHT + DAYLIGHT_MARGIN) {  // Sunrise happens
    turn(-TURNS);                           // Assuming negative rotation to open
    isOpen = true;
  }
  delay(1);

You provide NO feedback to know if the blind is open or closed and let that also control the motor movement.

The SN754410E is not a stepper motor driver, it is primarily a brushed DC motor or solenoid driver, and will work properly only with certain high impedance steppers.

You probably need a current limiting stepper driver, like the A4988 or DRV8825, but to give recommendations, we need to know the details of the stepper motor. At the very least, measure the winding resistance and post that value.

NEMA 17 specifies only the dimensions of the motor mounting faceplate.

Aha, I lied, the motor does have markings and it is 42STH34-0354A https://cdn-shop.adafruit.com/product-files/324/C140-A+datasheet.jpg. I measured and the resistance is 31 ohms.

Thanks for pointing that out. This motor won't torque this blind enough to damage it. I put a little disclaimer at the top of the code.

That motor is a high impedance stepper (34 Ohm coils according to the linked spec sheet) and will work with L29x or other bipolar brushed DC motor drivers like the SN754410.

Since a bipolar transistor driver can drop up to 4V internally, use a 14-16V motor power supply capable of delivering at least 1 Ampere for full torque. 5V won't work.

1 Like

Aha! It was a software problem. Here I'm setting the board pin #1 to input when I'm using it for digital out. We want to pass the board pin number to pinMode(), but the analog pin number to analogRead(). In the end I removed the following line and it's now working as expected.

I'm using a 12V power supply, relying on the Trinket's on-board voltage regulator. Thank you for the reply.

Surely not for the motor power supply.

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.