Stepper motor not working, only vibrating

Hi everyone,

I'm very new so I hope you bear* with me :). I'm working on a project I've found on YouTube (link: https://youtu.be/1O_1gUFumQM?si=rvuEjOq1rsucmCTi) but currently I'm stuck on it. To start what I want to do:

With Home Assistant send command to ESP32 Wroom to close or open blinds via mqtt protocol. Components I'm using:

  • ESP32 Wroom
  • DRV8825 stepper motor driver
  • 28BYJ-48 5V stepper motor (modified)
  • 5V power supply
  • 12V power supply

The ground of the power supply's is connected. The 28BYJ-48 is modified so it's now a bipolar stepper motor (by cutting the middle trace and not using the red wire). I can send a command to the ESP32 and the motor start vibrating and I can visually see its trying to go in one direction but its not moving otherwise.

What I have tried to fix it:

  • Changing the coils (A1<--> A2, B1<-->B2).
  • Changing the speed and adding microstepping in the code.
  • Trying different motor and a different driver.
  • Confirmed the motor is indeed running bipolar by measuring the resistance in the coils (can provide if needed).

Don't know if it is relevant but when I take out the 12V power supply and the motor is still running, when power almost runs out it suddenly moves as expected right before it runs out.

I have the following code for the ESP32. Its a bit different from the code in the tutorial because of the difference in components:

#include <Ticker.h>         //https://github.com/marcelloromani/Arduino-SimpleTimer/tree/master/SimpleTimer
#include <WiFi.h>           //if you get an error here you need to install the ESP8266 board manager 
#include <ESPmDNS.h>        //if you get an error here you need to install the ESP8266 board manager 
#include <PubSubClient.h>   //https://github.com/knolleary/pubsubclient
#include <ArduinoOTA.h>     //https://github.com/esp8266/Arduino/tree/master/libraries/ArduinoOTA
#include <AH_EasyDriver.h>  //http://www.alhin.de/arduino/downloads/AH_EasyDriver_20120512.zip

/*****************  START USER CONFIG SECTION *********************************/
/*****************  START USER CONFIG SECTION *********************************/
/*****************  START USER CONFIG SECTION *********************************/
/*****************  START USER CONFIG SECTION *********************************/

#define USER_SSID                 "Routers"
#define USER_PASSWORD             ",Password>"
#define USER_MQTT_SERVER          "<IP_Adress>"
#define USER_MQTT_PORT            1883
#define USER_MQTT_USERNAME        "<mqttuser>"
#define USER_MQTT_PASSWORD        "<mqttpassword>"
#define USER_MQTT_CLIENT_NAME     "BlindsMCU"         // Used to define MQTT topics, MQTT Client ID, and ArduinoOTA

#define STEPPER_SPEED             35                 //Defines the speed in RPM for your stepper motor
#define STEPPER_STEPS_PER_REV     1028                //Defines the number of pulses that is required for the stepper to rotate 360 degrees
#define STEPPER_MICROSTEPPING     0                 //Defines microstepping 0 = no microstepping, 1 = 1/2 stepping, 2 = 1/4 stepping 
#define DRIVER_INVERTED_SLEEP     1                   //Defines sleep while pin high.  If your motor will not rotate freely when on boot, comment this line out.

#define STEPS_TO_CLOSE            12                  //Defines the number of steps needed to open or close fully

#define STEPPER_DIR_PIN           12                  //D6
#define STEPPER_STEP_PIN          13                  //D7
#define STEPPER_SLEEP_PIN         14                  //D5
#define STEPPER_MICROSTEP_1_PIN   27                  //14
#define STEPPER_MICROSTEP_2_PIN   26                  //12
 
/*****************  END USER CONFIG SECTION *********************************/
/*****************  END USER CONFIG SECTION *********************************/
/*****************  END USER CONFIG SECTION *********************************/
/*****************  END USER CONFIG SECTION *********************************/
/*****************  END USER CONFIG SECTION *********************************/

WiFiClient espClient;
PubSubClient client(espClient);
Ticker stepperTicker;
Ticker checkinTicker;
AH_EasyDriver shadeStepper(STEPPER_STEPS_PER_REV, STEPPER_DIR_PIN ,STEPPER_STEP_PIN,STEPPER_MICROSTEP_1_PIN,STEPPER_MICROSTEP_2_PIN,STEPPER_SLEEP_PIN);

//Global Variables
bool boot = true;
int currentPosition = 0;
int newPosition = 0;
char positionPublish[50];
bool moving = false;
char charPayload[50];

const char* ssid = USER_SSID ; 
const char* password = USER_PASSWORD ;
const char* mqtt_server = USER_MQTT_SERVER ;
const int mqtt_port = USER_MQTT_PORT ;
const char *mqtt_user = USER_MQTT_USERNAME ;
const char *mqtt_pass = USER_MQTT_PASSWORD ;
const char *mqtt_client_name = USER_MQTT_CLIENT_NAME ; 




//Functions
void setup_wifi() {
  // We start by connecting to a WiFi network
  Serial.println();
  Serial.print("Connecting to ");
  Serial.println(ssid);

  WiFi.begin(ssid, password);

  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }

  Serial.println("");
  Serial.println("WiFi connected");
  Serial.println("IP address: ");
  Serial.println(WiFi.localIP());
}

void reconnect() 
{
  int retries = 0;
  while (!client.connected()) {
    if(retries < 150)
    {
      Serial.print("Attempting MQTT connection...");
      if (client.connect(mqtt_client_name, mqtt_user, mqtt_pass)) 
      {
        Serial.println("connected");
        if(boot == false)
        {
          client.publish(USER_MQTT_CLIENT_NAME"/checkIn","Reconnected"); 
        }
        if(boot == true)
        {
          client.publish(USER_MQTT_CLIENT_NAME"/checkIn","Rebooted");
        }
        // ... and resubscribe
        client.subscribe(USER_MQTT_CLIENT_NAME"/blindsCommand");
        client.subscribe(USER_MQTT_CLIENT_NAME"/positionCommand");
      } 
      else 
      {
        Serial.print("failed, rc=");
        Serial.print(client.state());
        Serial.println(" try again in 5 seconds");
        retries++;
        // Wait 5 seconds before retrying
        delay(5000);
      }
    }
    if(retries > 149)
    {
    ESP.restart();
    }
  }
}

void callback(char* topic, byte* payload, unsigned int length) 
{
  Serial.print("Message arrived [");
  String newTopic = topic;
  Serial.print(topic);
  Serial.print("] ");
  payload[length] = '\0';
  String newPayload = String((char *)payload);
  int intPayload = newPayload.toInt();
  Serial.println(newPayload);
  Serial.println();
  newPayload.toCharArray(charPayload, newPayload.length() + 1);
  if (newTopic == USER_MQTT_CLIENT_NAME"/blindsCommand") 
  {
    if (newPayload == "OPEN")
    {
      client.publish(USER_MQTT_CLIENT_NAME"/positionCommand", "0", true);
    }
    else if (newPayload == "CLOSE")
    {   
      int stepsToClose = STEPS_TO_CLOSE;
      String temp_str = String(stepsToClose);
      temp_str.toCharArray(charPayload, temp_str.length() + 1);
      client.publish(USER_MQTT_CLIENT_NAME"/positionCommand", charPayload, true);
    }
    else if (newPayload == "STOP")
    {
      String temp_str = String(currentPosition);
      temp_str.toCharArray(positionPublish, temp_str.length() + 1);
      client.publish(USER_MQTT_CLIENT_NAME"/positionCommand", positionPublish, true); 
    }
  }
  if (newTopic == USER_MQTT_CLIENT_NAME"/positionCommand")
  {
    if(boot == true)
    {
      newPosition = intPayload;
      currentPosition = intPayload;
      boot = false;
    }
    if(boot == false)
    {
      newPosition = intPayload;
    }
  }
  
}

void processStepper()
{
  if (newPosition > currentPosition)
  {
    #if DRIVER_INVERTED_SLEEP == 1
    shadeStepper.sleepON();
    #endif
    #if DRIVER_INVERTED_SLEEP == 0
    shadeStepper.sleepOFF();
    #endif
    shadeStepper.move(80, FORWARD);
    currentPosition++;
    moving = true;
  }
  if (newPosition < currentPosition)
  {
    #if DRIVER_INVERTED_SLEEP == 1
    shadeStepper.sleepON();
    #endif
    #if DRIVER_INVERTED_SLEEP == 0
    shadeStepper.sleepOFF();
    #endif
    shadeStepper.move(80, BACKWARD);
    currentPosition--;
    moving = true;
  }
  if (newPosition == currentPosition && moving == true)
  {
    #if DRIVER_INVERTED_SLEEP == 1
    shadeStepper.sleepOFF();
    #endif
    #if DRIVER_INVERTED_SLEEP == 0
    shadeStepper.sleepON();
    #endif
    String temp_str = String(currentPosition);
    temp_str.toCharArray(positionPublish, temp_str.length() + 1);
    client.publish(USER_MQTT_CLIENT_NAME"/positionState", positionPublish); 
    moving = false;
  }
  Serial.println(currentPosition);
  Serial.println(newPosition);
}

void checkIn()
{
  client.publish(USER_MQTT_CLIENT_NAME"/checkIn","OK"); 
}


//Run once setup
void setup() {
  Serial.begin(115200);
  shadeStepper.setMicrostepping(STEPPER_MICROSTEPPING);            // 0 -> Full Step                                
  shadeStepper.setSpeedRPM(STEPPER_SPEED);     // set speed in RPM, rotations per minute
  #if DRIVER_INVERTED_SLEEP == 1
  shadeStepper.sleepOFF();
  #endif
  #if DRIVER_INVERTED_SLEEP == 0
  shadeStepper.sleepON();
  #endif
  WiFi.mode(WIFI_STA);
  setup_wifi();
  client.setServer(mqtt_server, mqtt_port);
  client.setCallback(callback);
  ArduinoOTA.setHostname(USER_MQTT_CLIENT_NAME);
  ArduinoOTA.begin(); 
  delay(10);
  stepperTicker.attach_ms(((1 << STEPPER_MICROSTEPPING)*5800)/STEPPER_SPEED, processStepper);
  checkinTicker.attach(90, checkIn);  // 90 seconds
}

void loop() 
{
  if (!client.connected()) 
  {
    reconnect();
  }
  client.loop();
  ArduinoOTA.handle();
}


Thank you all in advance for your help. If I need to provide other data or if I'm listing this wrong please let me know I will change it ASAP.

Greetings.

Pass, too cold for that here.

Those motors can't do much higher than 12 RPM.
Try a much lower value first.

12 is a strapping pin. avoid if you can.
Leo..

Too late now, but starting with a known library and one of its samples is the best way to learn. Using a random YT creator's library is risky especially when you make physical modifications to a motor.
My suggestion is to start over with a new motor as I suggested. Here are 3 possibles of many.

I doubt that a modified motor is doing any better than a common one with an ULN chip.
Modification is only useful if you need torque at higher speeds, which I don' t see the need for in this application.
Leo..

Hi @Wawa ,

I was also wondering but just looked up the video and got this link to github

https://github.com/thehookup/Motorized_MQTT_Blinds

The modification is requested as well on that page as also in the video to apply higher voltage and get more torque ...

They cut the link on the internal board of the motor.

Regards
ec2021

Hi @bintley ,

I'd recommend to create a (more simple) sketch that does only control the stepper (e.g. turn right for 3 sec, stop for 1 sec and turn left for 3 seconds again) to test your wiring and components.

Get this running first before you go on with the complete sketch.

Good luck!
ec2021

Hello, about 2 years ago I posted this same method to convert a 5 wire unipolar stepper to a 4 wire bipolar stepper. howto modify a xxBJY stepper motor
one thing that can happen if you are not very carefull on removing the cover of the wires one or more of these hair thin coilwires get cut and the motor is dead. On trying to connect and operate the motor this specific effect of vibrate but not move can result from a cutted coil.

Thank you for the reaction. This indeed happened with one of the motors :sweat_smile:. Just to clearify if what I have done is correct, these are the resistance between the wires:

Red <--> Pink/Orange = 22 Ohm
Orange <--> Pink = 44 Ohm
Blue <--> Yellow = 44 Ohm

If I'm correct the orange and pink are coil A and blue and yellow coil B. The red wire is not used. I measure the resistance on the soldering pads.

Thank you! I've tried a more basic code where it is just turning (also tried doing it with AccelStepper):

const int stepPin = 18;
const int dirPin = 19;

void setup() {
  pinMode(stepPin, OUTPUT);
  pinMode(dirPin, OUTPUT);
  digitalWrite(dirPin, HIGH); // direction
}

void loop() {
  digitalWrite(stepPin, HIGH);
  delayMicroseconds(1000);
  digitalWrite(stepPin, LOW);
  delayMicroseconds(1000);
}

Indeed the reason I have modified it is because I needed more torque for the blinds to open or close. Speed is in this project unnecessary. The ULN2003 wouldn't work on the bigger blinds.

Thank you for your suggestions. Changed the pin layout and speed for future use.
:bear: