Welcome!

By registering with us, you'll be able to discuss, share and private message with other members of our community.

SignUp Now!
  • Guest, before posting your code please take these rules into consideration:
    • It is required to use our BBCode feature to display your code. While within the editor click < / > or >_ and place your code within the BB Code prompt. This helps others with finding a solution by making it easier to read and easier to copy.
    • You can also use markdown to share your code. When using markdown your code will be automatically converted to BBCode. For help with markdown check out the markdown guide.
    • Don't share a wall of code. All we want is the problem area, the code related to your issue.


    To learn more about how to use our BBCode feature, please click here.

    Thank you, Code Forum.

C++ Dog door Code issue

MacGyver

New Coder
I have this code for an automatic dog door. I am having an issue that I would like your input on. When I put the program on my NODEMCU board, the dog door is as quiet as can be. When I hit the user switch (to open the door) the door comes up, stops, pauses for the 3 sec duration and then brakes when it falls back to close. The 12% keeps the door from slamming and keeps the slack out of the cable from the motor to the door. When the door is closed, the motor should be off (disconnected). However, I hear the motor hum, so I pull on the cable and there was tension on the cable. I used my o-scope and can see that there is still a 4k oscillation with about a 4% duty cycle. So the board isn't truly going to 0% so it seems. I tried using a Wemos D1 mini, and an Arduino UNO (had to change the PWM there) and they all gave me the same results where the motor can't be at rest. What am I missing here? I am not a professional programmer, I just tinker so I am at a loss here. I know it's like a states machine which I am very familiar with from teaching Engineering in high school but it was using stepper motors which react differently and not a good choice for this application.

One last thing. I used an Opto Isolator from the D1 output to the opto then from there to the motor driver. I put the input to the opto on D6 and the other side to ground. I tried to toggle this to cut it completely off but I couldn't get the stupid thing to send a digitalWrite(OPTO, LOW); It only stayed high no matter how I tried to get it to change.

Thanks for all your help!!!! I do appreciate it....


Code:
// Pin Definitions
const int MOTOR_PIN = D1;        // PWM output to motor driver
const int USER_SWITCH = D2;      // Momentary switch input
const int SWITCH_START = D3;     // Door starting position switch
const int SWITCH_MID = D4;       // Door halfway position switch
const int SWITCH_END = D5;       // Door fully open position switch
const int LED_PIN = LED_BUILTIN; // Status LED
// Constants
const int PWM_FREQ = 4000;      // PWM frequency in Hz
const float HOLD_DUTY = 18.0;   // Holding duty cycle
const float BRAKE_DUTY = 12.0;  // Braking duty cycle
const float SLOW_DUTY = 40.0;   // Slower duty cycle for top approach
const float START_DUTY = 85.0;  // Initial opening duty cycle
const int HOLD_TIME = 3000;     // Hold time in milliseconds
// Door states
enum DoorState {
  CLOSED,
  OPENING,
  OPEN_HOLD,
  CLOSING
};
// Global variables
DoorState currentState = CLOSED;
unsigned long lastStateChange = 0;
float currentDuty = 0;
void setup() {
  // Configure pins
  pinMode(MOTOR_PIN, OUTPUT);
  pinMode(USER_SWITCH, INPUT_PULLUP);
  pinMode(SWITCH_START, INPUT_PULLUP);
  pinMode(SWITCH_MID, INPUT_PULLUP);
  pinMode(SWITCH_END, INPUT_PULLUP);
  pinMode(LED_PIN, OUTPUT);
  // Set PWM frequency
  analogWriteFreq(PWM_FREQ);
  // Initialize motor off
  digitalWrite(MOTOR_PIN, LOW);
  // Initialize serial for debugging
  Serial.begin(115200);
  Serial.println("\nDoor Control System");
  Serial.println("==================");
}
void setMotorDuty(float dutyPercent) {
  int pwmValue = (dutyPercent / 100.0) * 1023;
  pwmValue = constrain(pwmValue, 0, 1023);
 
  if (dutyPercent == 0) {
    digitalWrite(MOTOR_PIN, LOW);  // Complete shutoff
  } else {
    analogWrite(MOTOR_PIN, pwmValue);
  }
 
  currentDuty = dutyPercent;
 
  Serial.print("Duty Cycle: ");
  Serial.print(dutyPercent, 1);
  Serial.println("%");
}
void updateDoorState() {
  bool userButton = !digitalRead(USER_SWITCH);  // D2
  bool atStart = !digitalRead(SWITCH_START);    // D3
  bool atMid = !digitalRead(SWITCH_MID);        // D4
  bool atEnd = !digitalRead(SWITCH_END);        // D5
  unsigned long currentTime = millis();
  switch (currentState) {
    case CLOSED:
      if (userButton) {
        currentState = OPENING;
        lastStateChange = currentTime;
        setMotorDuty(START_DUTY);  // Start at 85%
        Serial.println("State: OPENING");
      }
      break;
    case OPENING:
      if (atMid && currentDuty > SLOW_DUTY) {
        setMotorDuty(SLOW_DUTY);
        Serial.println("Slowing for approach");
      }
      
      if (atEnd) {
        currentState = OPEN_HOLD;
        lastStateChange = currentTime;
        setMotorDuty(HOLD_DUTY);
        Serial.println("State: HOLDING");
      }
      break;
    case OPEN_HOLD:
      if (!userButton && (currentTime - lastStateChange >= HOLD_TIME)) {
        currentState = CLOSING;
        setMotorDuty(BRAKE_DUTY);
        Serial.println("State: CLOSING");
      }
      break;
    case CLOSING:
      if (userButton) {
        currentState = OPENING;
        lastStateChange = currentTime;
        setMotorDuty(START_DUTY);
        Serial.println("State: REOPENING");
      }
      else if (atStart) {
        currentState = CLOSED;
        setMotorDuty(0);
        Serial.println("State: CLOSED");
      }
      break;
  }
  digitalWrite(LED_PIN, currentState != CLOSED);
}
void loop() {
  updateDoorState();
  delay(10);
}
 
Your code looks quite solid for the most part, and it sounds like you've set up the motor logic pretty effectively. The hum you're experiencing suggests that the motor is still receiving a small amount of power, possibly due to residual PWM output or wiring issues with the opto-isolator. Let's explore a few strategies to troubleshoot and possibly solve this issue.

1. Ensure Full Shutdown of Motor​

Your code already has logic to shut off the motor with digitalWrite(MOTOR_PIN, LOW) in setMotorDuty(), which should work theoretically. However, PWM signals can sometimes still leave a trace of residual voltage.

Try using analogWrite(MOTOR_PIN, 0); in place of digitalWrite(MOTOR_PIN, LOW); to ensure no PWM signal is sent, as the analogWrite() function should completely stop PWM output.

2. Check Pull-Up/Pull-Down Configuration​

Verify that the motor driver and opto-isolator’s logic are not leaving the motor pin in a “floating” state (where it isn’t driven low or high definitively). If digitalWrite(MOTOR_PIN, LOW) doesn’t fully disengage the motor, check the circuit’s pull-up and pull-down resistors on the motor input. Adding a pull-down resistor (e.g., 10kΩ) might help to keep the motor truly off.

3. Test Opto-Isolator Control​

Your opto-isolator setup might be retaining a "high" signal even after you set it to LOW. Try testing the behavior by bypassing the opto-isolator and directly driving the motor signal (if safe). If the hum disappears when the opto-isolator is bypassed, you may need a stronger pull-down resistor on the opto-isolator output, or the opto-isolator might need a slight change in wiring or power control to respond to the LOW signal effectively.

4. Check Power Supply and Grounding​

Power supplies sometimes introduce noise, which could appear as a hum or residual PWM signal. Ensure that all grounds (motor, opto-isolator, NodeMCU) are solidly connected, as floating grounds could cause unintended signals to persist.
 

New Threads

Buy us a coffee!

Back
Top Bottom