DC Motor H-Bridge start movement

Dear all,
i set up a smarthome awning control.
Components:

  • ESP8266
  • BTS7960
  • Hall Sensor
  • 12V DC motor

The DC motor is able to rotate clockwise and counterclockwise via the H-Bridge.
Commands are triggered via MQTT.
Rotations are counted via Hall Sensor.

However i do have a problem: When i start up the ESP8266 (or flash or reset it) the DC motor is immediately rotating for ~5 second. Then it stop and everything works from there on.
PWM pins are D3 (pin_pwm_pos) and D4 (pin_pwm_neg).
How can i inhibit these first 5 second rotations?

Code below:

#include <Arduino.h>
#include <assert.h>
#include <ESP8266WiFi.h>
#include <PubSubClient.h>
#include <ESP8266mDNS.h>
#include <WiFiUdp.h>
#include <ArduinoOTA.h>


const char* ssid = "XXXXX";
const char* password = "XXXXX";
const char* mqtt_server = "XXXX";
const int mqttPort = 1883;
const char* mqttUser = "XXXX";
const char* mqttPassword = "XXXXX";

WiFiClient espClient;
PubSubClient client(espClient);

const int pin_pwm_pos = 0; //D3
const int pin_pwm_neg = 2; //D4
//const int pin_ena_pos = 16; //D0
//const int pin_ena_neg = 5; //D1

int rotation_direction = 0;
int rotation_speed = 100;
int rotation_pwm = rotation_speed * 10.23;
int max_rotation = 10;
int target_percentage = 0;
int target_rotation = 0;
int actual_percentage = 0;
int max_rotation_duration = 2000; //ms


const uint8_t interruptPin = 5; //D1

volatile byte interruptCounter = 0;
volatile unsigned int isrMillis;
volatile unsigned int duration = 0; //ms
int numberOfInterrupts = 0;
//int rpm = 0;
volatile unsigned int timeold;
void ICACHE_RAM_ATTR handleInterrupt();

void setup_wifi() {
  delay(10);
  // 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(".");
  }

  randomSeed(micros());

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

void MQTTCallback(char* topic, byte* payload, unsigned int length) {
  String PayloadString = "";
  for (int i = 0; i < length; i++) {
    PayloadString = PayloadString + ( char)payload[i];
  }

  Serial.println("New message arrived");
  Serial.println(topic);
  Serial.println(PayloadString);

  if (strcmp(topic, "ArduinoMarkise/cmnd/direction") == 0) {
    Serial.println("set new direction");
    rotation_direction = PayloadString.toInt();
    if (rotation_direction == 0) {
      client.publish("ArduinoMarkise/fb/log", "Rotation direction 0 recieved");   
    }

  }

  if (strcmp(topic, "ArduinoMarkise/cmnd/speed") == 0) {
    Serial.println("set new speed");
    rotation_speed = PayloadString.toInt();
    rotation_pwm = rotation_speed * 10.23;
  }

  if (strcmp(topic, "ArduinoMarkise/cmnd/max_rotation") == 0) {
    Serial.println("set new max rotation");
    max_rotation = PayloadString.toInt();
  }

  if (strcmp(topic, "ArduinoMarkise/cmnd/target_percentage") == 0) {
    Serial.println("set new target_percentage");
    target_percentage = PayloadString.toInt();
    target_rotation = target_percentage / 100 * max_rotation;
  }

}

void reconnect() {
  while (!client.connected()) {
    // Create a random client ID
    String clientId = "ESP8266Casdlient-";
    clientId += String(random(0xffff), HEX);

    // Attempt to connect
    if (client.connect(clientId.c_str())) {
      Serial.println("subscribe objects");
      client.subscribe("ArduinoMarkise/cmnd/direction");
      client.subscribe("ArduinoMarkise/cmnd/speed");
      client.subscribe("ArduinoMarkise/cmnd/max_rotation");
      client.subscribe("ArduinoMarkise/cmnd/target_percentage");

      client.publish("ArduinoMarkise/cmnd/target_percentage", 0);
      client.publish("ArduinoMarkise/fb/actual_percentage", 0);  
    }
    else
    {
      Serial.print("failed, rc=");
      Serial.print(client.state());
      Serial.println(" try again in 5 seconds");

      delay(5000);
    }
  }
}



void setup() {
  Serial.begin(115200);

  pinMode(pin_pwm_pos, OUTPUT);
  pinMode(pin_pwm_pos, OUTPUT);
  analogWrite(pin_pwm_pos, 0);
  analogWrite(pin_pwm_neg, 0);

  setup_wifi();
  client.setServer(mqtt_server, 1883);
  client.setCallback(MQTTCallback);

  ArduinoOTA.setHostname("Markise_control");

  ArduinoOTA.onStart([]() {
    String type;
    if (ArduinoOTA.getCommand() == U_FLASH) {
      type = "sketch";
    } else { // U_FS
      type = "filesystem";
    }

    // NOTE: if updating FS this would be the place to unmount FS using FS.end()
    Serial.println("Start updating " + type);
  });
  ArduinoOTA.onEnd([]() {
    Serial.println("\nEnd");
  });
  ArduinoOTA.onProgress([](unsigned int progress, unsigned int total) {
    Serial.printf("Progress: %u%%\r", (progress / (total / 100)));
  });
  ArduinoOTA.onError([](ota_error_t error) {
    Serial.printf("Error[%u]: ", error);
    if (error == OTA_AUTH_ERROR) {
      Serial.println("Auth Failed");
    } else if (error == OTA_BEGIN_ERROR) {
      Serial.println("Begin Failed");
    } else if (error == OTA_CONNECT_ERROR) {
      Serial.println("Connect Failed");
    } else if (error == OTA_RECEIVE_ERROR) {
      Serial.println("Receive Failed");
    } else if (error == OTA_END_ERROR) {
      Serial.println("End Failed");
    }
  });
  ArduinoOTA.begin();
  Serial.println("Ready");
  Serial.print("IP address: ");
  Serial.println(WiFi.localIP());



  pinMode(interruptPin, INPUT);
  attachInterrupt(digitalPinToInterrupt(interruptPin), handleInterrupt, FALLING);

  



}

void handleInterrupt() {
  if (rotation_direction == 1) {
    interruptCounter++;
  } else if (rotation_direction = -1) {
    interruptCounter--;
  }
  
  isrMillis = millis();
  
}

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

  ArduinoOTA.handle();

  client.loop();

  if (rotation_direction == 0) {
    isrMillis = millis();
  }
  
  timeold  = millis();
  duration = timeold-isrMillis;

  if (duration > max_rotation_duration) {
      rotation_direction = 0;
      analogWrite(pin_pwm_pos, 0);
      analogWrite(pin_pwm_neg, 0);
      client.publish("ArduinoMarkise/cmnd/direction", 0);   
      client.publish("ArduinoMarkise/fb/log", "Duration exceeded");   
  }

  switch (rotation_direction) {
  case 1:

    if (interruptCounter >= target_rotation) {
      rotation_direction = 0;
      analogWrite(pin_pwm_pos, 0);
      analogWrite(pin_pwm_neg, 0);
      client.publish("ArduinoMarkise/cmnd/direction", 0);     
      client.publish("ArduinoMarkise/fb/log", "Positive target position reached");    
    } else {
      analogWrite(pin_pwm_pos, rotation_pwm);
      analogWrite(pin_pwm_neg, 0);
      client.publish("ArduinoMarkise/fb/log", "Positive rotation direction");   
    }

    actual_percentage = ( interruptCounter * 100 ) / max_rotation ;
    client.publish("ArduinoMarkise/fb/actual_percentage", String(actual_percentage).c_str());

    break;

  case -1:

    if (interruptCounter == 0) {
      rotation_direction = 0;
      analogWrite(pin_pwm_pos, 0);
      analogWrite(pin_pwm_neg, 0);
      client.publish("ArduinoMarkise/cmnd/direction", 0);      
      client.publish("ArduinoMarkise/fb/log", "Target position 0 reached");    
    } else {
      analogWrite(pin_pwm_pos, 0);
      analogWrite(pin_pwm_neg, rotation_pwm);
      client.publish("ArduinoMarkise/fb/log", "Negative rotation direction");   
    }

    actual_percentage = ( interruptCounter * 100 ) / max_rotation ;      
    client.publish("ArduinoMarkise/fb/actual_percentage", String(actual_percentage).c_str());

    break;

  case 0:

    analogWrite(pin_pwm_pos, 0);
    analogWrite(pin_pwm_neg, 0);

    duration = 0;

    break;

  }

  delay(100);


}

From what I can see from this page: ESP8266 Pinout Reference: Which GPIO pins should you use? | Random Nerd Tutorials
You've chosen pins that have pull-ups and have to be HIGH at boot time for boot to work, so you
need to choose different pins for you motor PWM, unless there's a separate enable input to the
motor driver that can override them.

Hello MarkT, i think you are right!
I checked your link:

"There are certain pins that output a 3.3V signal when the ESP8266 boots. This may be problematic if you have relays or other peripherals connected to those GPIOs. The following GPIOs output a HIGH signal on boot:

GPIO16
GPIO3
GPIO1
GPIO10
GPIO9

GPIO4 and GPIO5 are the most safe to use GPIOs if you want to operate relays."

I am using now D1 (GPIO5) and D2 (GPIO4) for the PWMs.
The DC motor is now not actuating after ESP8266 restart :slight_smile:

Thank you alot!

Excellent.

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