Motor not responding

I have developed a strange issue with my project, which was working fine. I have made no code changes that I can see. the problem is that I have a vertical sliding door with reed switches at top and bottom. the code sends the door up when it is supposed to but when it gets to the top, the switch is triggered, verified from a serial output as well as a lcd output, but the motor doesnt stop. I'll post the relevent code.

void motorup()  // this function will run the motor as long as topswitch has not been triggered ( is not HIGH)
{
  BotSwtchState = digitalRead(BotSwtch);
  TopSwtchState = digitalRead(TopSwtch);
//  TopSwtch2State = digitalRead(TopSwtch2);
    while (TopSwtchState != HIGH) {
    analogWrite(PWM, 10);
    digitalWrite(DIR, HIGH);
    TopSwtchState = digitalRead(TopSwtch);
//    TopSwtch2State = digitalRead(TopSwtch2);
  }
  delay(100);
  analogWrite(PWM, 0);
  digitalWrite(coopDoorClosedLed, LOW);  // turns on coopDoorClosedLed (green)
  digitalWrite(coopDoorOpenLed, HIGH);   // turns off coopDoorOpenLed (red)
}

If that was really relevant, you would have discovered the problem! Post the ENTIRE code.

//Locking, Automatic Chicken Coop Door
//By Mike Roberts 2024  (based off of original code by Seth Johnson  Land To House llc 2016)
//#include <Arduino.h>
#include <ElegantOTA.h>
#include <AsyncTCP.h>
#include <WiFi.h>
#include <WiFiClient.h>
#include <ESPAsyncWebServer.h> 
#include <Wire.h>
#include <LiquidCrystal_I2C.h>
LiquidCrystal_I2C lcd(0x27, 20, 4);
#include <DallasTemperature.h>
#define CoolRelay 32
#define HeatRelay 33
#define ONE_WIRE_BUS 4
const boolean SerialDisplay = true;  // print debug messages or not to serial
//This section is for initializing things:
//const int led = 13;
int tcrt;
const int PWM = 26;   //enables PWM on the drv8801 motor controller.
const int DIR = 27;   //send high or low to DIR on the motor controller.
const int red = 14;   // red LED heating
const int blue = 12;  // blue LED cooling
const int coopDoorOpenLed = 13;
const int coopDoorClosedLed = 23;
const int lightSensorPin = 34;  //Initialize "lightSensor" This is the photoresistor.
const int lightSensorPin2 = 32;
const int BotSwtch = 18;
const int TopSwtch = 19;
const int TopSwtch2 = 17;
int lightVal = 0;
int lightVal2 = 0;
int BotSwtchState = 0;
int TopSwtchState = 0;  //These are the variables that hold the state of the reed switches
int TopSwtch2State = 0;
//int localIPA = 0;
OneWire oneWire(ONE_WIRE_BUS);
DallasTemperature sensors(&oneWire);

//Set WiFi Credentials
const char *ssid = "chicken";
const char *password = "********";

// Try and get a static IP address (so we can find the device for web pages)
IPAddress local_IP(192, 168, 8, 88); // change 103 to be unique on your system
IPAddress gateway(192, 168, 8, 1);
IPAddress subnet(255, 255, 255, 0);

// To get the local time we must include DNS servers. Google's used here.
IPAddress primaryDNS(1, 1, 1, 1);
IPAddress secondaryDNS(1, 0, 0, 1);

const char *wl_status_to_string(wl_status_t status);

//WebServer server(80);
AsyncWebServer server(80);

void updateParm1(std::string *htmlString, std::string findPattern, std::string replaceWith)
{
  // Copy the string into something we can easily work with locally
  std::string tempString = (*htmlString);

  // Find the FIRST occurence of the placeholder @parm1
  size_t Lightval1Pos = tempString.find(findPattern);

  // Replace all the occurences (it might be in multiple places)
  while (Lightval1Pos != std::string::npos) {
    log_d("Found %s", findPattern.c_str());
    tempString.replace(Lightval1Pos, findPattern.length(), replaceWith);
    Lightval1Pos = tempString.find(findPattern);
  }

  // Update the html string passed to us originally
  *htmlString = tempString;
}
void updateParm2(std::string *htmlString, std::string findPattern, std::string replaceWith)
{
  // Copy the string into something we can easily work with locally
  std::string tempString = (*htmlString);

  // Find the FIRST occurence of the placeholder @parm1
  size_t tempFPos = tempString.find(findPattern);

  // Replace all the occurences (it might be in multiple places)
  while (tempFPos != std::string::npos) {
    log_d("Found %s", findPattern.c_str());
    tempString.replace(tempFPos, findPattern.length(), replaceWith);
    tempFPos = tempString.find(findPattern);
  }

  // Update the html string passed to us originally
  *htmlString = tempString;
} 
void updateParm3(std::string *htmlString, std::string findPattern, std::string replaceWith)
{
  // Copy the string into something we can easily work with locally
  std::string tempString = (*htmlString);

  // Find the FIRST occurence of the placeholder @parm1
  size_t topswitchPos = tempString.find(findPattern);

  // Replace all the occurences (it might be in multiple places)
  while (topswitchPos != std::string::npos) {
    log_d("Found %s", findPattern.c_str());
    tempString.replace(topswitchPos, findPattern.length(), replaceWith);
    topswitchPos = tempString.find(findPattern);
  }

  // Update the html string passed to us originally
  *htmlString = tempString;
} 
void updateParm4(std::string *htmlString, std::string findPattern, std::string replaceWith)
{
  // Copy the string into something we can easily work with locally
  std::string tempString = (*htmlString);

  // Find the FIRST occurence of the placeholder @parm1
  size_t botswitchPos = tempString.find(findPattern);

  // Replace all the occurences (it might be in multiple places)
  while (botswitchPos != std::string::npos) {
    log_d("Found %s", findPattern.c_str());
    tempString.replace(botswitchPos, findPattern.length(), replaceWith);
    botswitchPos = tempString.find(findPattern);
  }

  // Update the html string passed to us originally
  *htmlString = tempString;
}
void updateParm5(std::string *htmlString, std::string findPattern, std::string replaceWith)
{
  // Copy the string into something we can easily work with locally
  std::string tempString = (*htmlString);

  // Find the FIRST occurence of the placeholder @parm1
  size_t topswitch2Pos = tempString.find(findPattern);

  // Replace all the occurences (it might be in multiple places)
  while (topswitch2Pos != std::string::npos) {
    log_d("Found %s", findPattern.c_str());
    tempString.replace(topswitch2Pos, findPattern.length(), replaceWith);
    topswitch2Pos = tempString.find(findPattern);
  }

  // Update the html string passed to us originally
  *htmlString = tempString;
} 
void motordown()  //code for sending door down
{
  BotSwtchState = digitalRead(BotSwtch);
  while (BotSwtchState != HIGH) {
    analogWrite(PWM, 100);
    digitalWrite(DIR, LOW);
    BotSwtchState = digitalRead(BotSwtch);
  }
  delay(1000);                            //wait 1 seconds before turning off the motor to let the locks engage at the bottom
  analogWrite(PWM, 0);                    // now turn off motor
  digitalWrite(coopDoorClosedLed, HIGH);  // turns on coopDoorClosedLed (green)
  digitalWrite(coopDoorOpenLed, LOW);     // turns off coopDoorOpenLed (red)
}

void motorup()  // this function will run the motor as long as switch 2 has not been triggered
{
  BotSwtchState = digitalRead(BotSwtch);
  TopSwtchState = digitalRead(TopSwtch);
//  TopSwtch2State = digitalRead(TopSwtch2);
    while (TopSwtchState != HIGH) {
    analogWrite(PWM, 5);
    digitalWrite(DIR, HIGH);
    TopSwtchState = digitalRead(TopSwtch);
//    TopSwtch2State = digitalRead(TopSwtch2);
  }
  delay(100);
  analogWrite(PWM, 0);
  digitalWrite(coopDoorClosedLed, LOW);  // turns on coopDoorClosedLed (green)
  digitalWrite(coopDoorOpenLed, HIGH);   // turns off coopDoorOpenLed (red)
}

void setup()  //This only runs once.
{
  Serial.begin(115200);  // initialize the serial communications:
  //connect to WiFi
  WiFi.mode(WIFI_STA);
  WiFi.persistent(false);
  WiFi.setAutoReconnect(true);
  WiFi.setSleep(false);
  WiFi.config(local_IP, gateway, subnet, primaryDNS, secondaryDNS);
  wl_status_t reply = WiFi.begin(ssid, password);
  log_w("Result: %s", wl_status_to_string(reply));
  // Just to be sure we have a 404 response on unknown requests
  server.onNotFound(
      [](AsyncWebServerRequest *request) {
        // Send back a plain text message (can be made html if required)
        request->send(404, "text/plain", "404 - Page Not Found, oops!");
      });
  server.on("/", HTTP_GET, [](AsyncWebServerRequest *request) {
    // Tell the system that we will be sending back html (not just plain text)
    AsyncResponseStream *response = request->beginResponseStream("text/html");
    // Format the html as a RAW literal so we don't have to escape all the quotes (and more)
    std::string htmlOutput = R"(
   <html>
     <head>
     <script src="https://kit.fontawesome.com/73839aa4ec.js" crossorigin="anonymous"></script>
      <body>
        <meta name="viewport" content="width=device-width, initial-scale=1">
        <link rel="stylesheet" href="https://use.fontawesome.com/releases/v5.7.2/css/all.css" integrity="sha384-fnmOCqbTlWIlj8LyTjo7mOUStjsKC4pOpQbqyi7RrhN7udi9RwhKkMHpvLbHG9Sr" crossorigin="anonymous">
        <style>
          html {
           font-family: Arial;
           display: inline-block;
           margin: 0px auto;
           text-align: center;
          }
          h2 { font-size: 3.0rem; }
          p { font-size: 2.0rem; }
          k { font-size: 1.5rem; }
          .units { font-size: 1.2rem; }
          .ds-labels{
            font-size: 1.5rem;
            vertical-align:middle;
            padding-bottom: 15px;
          }
        </style>
      </body>
    </head>
      <body>
        <h2>Chicken Coop Status Page</h2>
        <p>
          <i class="fas fa-thermometer-half" style="color:#059e8a;"></i>
          <span class="ds-labels">Temperature Fahrenheit</span>
          <span id="temperaturef">@tempF</span>
          <sup class="units">&deg;F</sup>
        </p>
        <head>
          <title>Chicken Coop Status Page</title>
          <style>
            body {
              background-color: forestgreen;
              font-family: Arial, Sans-Serif;
              color: yellow;
            }
            #myValue {
              width: 50px;
            }
          </style>
        </head>
        <body>
          <h1>Light Sensor Value: @Lightval1</h1>
          <h1>Top Switch State: @topswitch</h1>
          <h1>Bottom Switch State: @botswitch</h1>
          <h1>Top Switch 2 State: @topswitch2</h1>
        <div style="position: relative">
            <k style="position: fixed; bottom: 0; width:100%; text-align: center;"> Revision 4-24-2026
            </k>
        </div>
    </body>
</html>
  )";
    updateParm1(&htmlOutput, "@Lightval1", std::to_string(lightVal));
    updateParm2(&htmlOutput, "@tempF", std::to_string(sensors.getTempFByIndex(0)));
    updateParm3(&htmlOutput, "@topswitch", std::to_string(TopSwtchState));
    updateParm4(&htmlOutput, "@botswitch", std::to_string(BotSwtchState));
    updateParm5(&htmlOutput, "@topswitch2", std::to_string(TopSwtch2State));   
    // Output the stuffed string (yes, that's a term)
    response->printf(htmlOutput.c_str());

    // Send back all the text/html for a standard web page
    request->send(response);
  });
 
  ElegantOTA.begin(&server);  // Start ElegantOTA
  server.begin();
  Serial.println("HTTP server started"); 
 
  lcd.init();  // set up the LCD's number of columns and rows:
  lcd.backlight();
  sensors.begin();
  pinMode(red, OUTPUT);
  pinMode(blue, OUTPUT);
  pinMode(CoolRelay, OUTPUT);
  pinMode(HeatRelay, OUTPUT);
  pinMode(PWM, OUTPUT);
  pinMode(DIR, OUTPUT);  // set the motor control pins as outputs. 
  pinMode(coopDoorOpenLed, OUTPUT);
  pinMode(coopDoorClosedLed, OUTPUT);
  pinMode(BotSwtch, INPUT_PULLUP);
  pinMode(TopSwtch, INPUT_PULLUP);
  pinMode(TopSwtch2, INPUT_PULLUP);
  
  BotSwtchState = digitalRead(BotSwtch);
  TopSwtchState = digitalRead(TopSwtch);
  TopSwtch2State = digitalRead(TopSwtch2);
  //  TestBtnState = digitalRead(TestBtn);
 
  if (BotSwtchState != HIGH)  //if BotSwtchState is not high then go to the while statement
  {
    while (BotSwtchState != HIGH)  // this function will run the motor down as long as switch 1 has not been triggered
    {
      analogWrite(PWM, 100);                  // turn on motor and set speed to 255
      digitalWrite(DIR, LOW);                 // DIR LOW=down HIGH=up
      BotSwtchState = digitalRead(BotSwtch);  //read the state of the switch again to make sure that it has not been triggered
      TopSwtchState = digitalRead(TopSwtch);  //read the state of switch 2 (the top one) and place it in TopSwtchState
    }
    delay(500);
    analogWrite(PWM, 0);                    // once TopSwtchState has been triggered turn off the motor
    digitalWrite(coopDoorClosedLed, HIGH);  // turns on coopDoorClosedLed (green)
    digitalWrite(coopDoorOpenLed, LOW);
  } 
}


//this runs over and over
void loop() {
  ElegantOTA.loop();
  //Code for OTA
  sensors.requestTemperatures();
  float temperature = sensors.getTempFByIndex(0);
  lightVal = analogRead(lightSensorPin);  //read the light sensor and place it in lightval
  lcd.home();
  char buffer[50];
  sprintf(buffer, "LSV: %4d", (analogRead(lightSensorPin)));  // was A0 which is now 19 try 19 if lightSensorPin doesnt work
  lcd.setCursor(0, 0);
  lcd.print(buffer);
  lcd.setCursor(10, 0);
  lcd.print("Temp:");  //  sprintf(buffer, "Temp: %f\337F", temperature);
  lcd.print(sensors.getTempFByIndex(0));
  lcd.print("\337F");  //  lcd.print (buffer);
  Serial.print(" Light sensor value: ");
  Serial.println(analogRead(lightSensorPin));
  Serial.print("      ");
  Serial.print(sensors.getTempFByIndex(0));
  Serial.println("\337F");
  if (temperature < 40)  //changed temp to 40
  {
    digitalWrite(red, HIGH);
    digitalWrite(blue, LOW);
    Serial.println("      Heating");
    digitalWrite(CoolRelay, 0);
    digitalWrite(HeatRelay, 1);
    delay(3000);
  } else if (temperature > 40 && temperature < 85)  //changed temp to 40
  {
    digitalWrite(red, LOW);
    digitalWrite(blue, LOW);
    Serial.println("      All Off");
    digitalWrite(CoolRelay, 0);
    digitalWrite(HeatRelay, 0);
  } else if (temperature > 85) {
    digitalWrite(CoolRelay, 1);
    digitalWrite(HeatRelay, 0);
    digitalWrite(red, LOW);
    digitalWrite(blue, HIGH);
    Serial.println("      Cooling ");
  }
  BotSwtchState = digitalRead(BotSwtch);
  Serial.print(" Bottom Switch Value: ");  // display "Bottom Switch Value:"
  Serial.println(digitalRead(BotSwtch));
  sprintf(buffer, "Bot  Sw: %d", BotSwtchState);
  lcd.setCursor(0, 1);
  lcd.print(buffer);
  TopSwtchState = digitalRead(TopSwtch);
  Serial.print(" Top Switch Value: ");  // display "Top Switch Value:"
  Serial.println(digitalRead(TopSwtch));
  sprintf(buffer, "Top  Sw: %d", TopSwtchState);
  lcd.setCursor(0, 2);
  lcd.print(buffer);
  TopSwtch2State = digitalRead(TopSwtch2);
  Serial.print(" Top Switch 2 Value: ");  // display "Top Switch Value:"
  Serial.println(digitalRead(TopSwtch2));
  sprintf(buffer, "Top Sw2: %d", TopSwtch2State);
  lcd.setCursor(0, 3);
  lcd.print(buffer);
 
  if (TopSwtchState == HIGH && lightVal < 10) {
    delay(30000);
    motordown();
  } else if (BotSwtchState == HIGH && lightVal > 400) {
    delay(5000);
    motorup();
  }
}

// Update one or more parameters in the web page

I just observed an odd behavior, not sure its relevent or not. I set all the pwm numbers to be really low thinking it was going to fast and blew by the switch. after updating the code the moror runs slow on its initial closing, but when it runs the "motorup" routine it is going fast still, not as fast as it was but not as slow as the initial motor run. not sure if that relevant or not but seems odd.

Thank you for the code. How many calls to other code are blocking? Have you written a program to just test the switch and report the status as it changes?

Oh, are you de-bouncing the switch tests?

All "while" constructions are blocking until the while is complete.

no other hardware like caps or resistors just the internal pullup in the esp32. the swithches are magnetic switches btw, if that matters. not sure what you mean by "blocking".

The execution of the code you have to test for the switches cannot occur during the time other code is looping waiting for something to happen. That is called blocking. If your code is off doing some thing else when the switch is triggered, it cannot be found in time and will return to the normal position.

this coop door has been working perfectly for the past years with the exact same hardware etc. nothing has changed exept I just had to replace the esp32 itself as well as the Pololu MAX14870 driver carrier. because i tried using a bad power supply.

well isnt it always waiting, either for a light level to reach a limit or a temp. isnt that what a while does?

Then something else has happened as well.

There is no reason for a while if you just test for the occurrence often enough.

you mean use an if or else if instead? the while is only waiting for a few moments once the motorup or motor down is triggered and it only takes a few seconds for the door to open or close.

Easily checked with an Ohmmeter on the switch contacts. Or a volt meter is the switch is energized.

Failure after years could be burned/sticking relay contacts, because the builder forgot to use snubber circuits across the motor.

Hi, @strebor71

Can I suggest you run some test codes that check each limit switch and motor control?
Thanks.... Tom.... :smiley: :+1: :coffee: :australia:

good idea, will do

You replaced the two major components plus the code. I wouldn't call that nothing!

Well, i mean configuration wise, It is the same esp model and i didnt change the code, until this problem started.

The original code looks OK and if it worked once it should still work. I'm looking for something that changed that could explain the problem.

i tried using a bad power supply.

What prompted you to try a different supply?

Hi @strebor71
You have two similar functions in your code—one for moving the door up, and the other for moving it down. You wrote that when moving up, the door doesn't stop when the limit switch is triggered. What about moving down?
Does the same behavior occur?

  • You need to show us a schematic that shows all the components in the project and their interconnections.
    This will expose design problems.
    Show us good images of your wiring too.

  • Dirt, grime, and water damage can cause many problems.

Over the years of this being in operation once in a while the motor would slow down or sometimes stop moving at all and I found that the culprit was the power supply that has gone bad, I just use recycled supplies I get from wherever, thirft store etc. I had found one that looked like a better quality one than i had and didnt test it at all and it had a short in it or something. I didn't really even need to replace it, which is killing me. so stupid mistake on me.