How do I make a servo stop and return if it hits resistance?

Hello everyone,

I want to control a cat door with a servo. The servo will stop and turn back to its previous position when it hits resistance. I tried with “millis()” but it did not work (see the code below). I found an example with 1-ohm, 5-watt metal film resistor here, but I am wondering if there is a possible solution with some code changes.
Any ideas?

#include <Adafruit_ILI9340.h>
#include <Servo.h>

Servo myservo;  // create servo object to control a servo
// twelve servo objects can be created on most boards

int pos = 95;    // variable to store the servo position
unsigned long currentTime;
unsigned long previousTime;

void setup() {
  myservo.attach(9);  // attaches the servo on pin 9 to the servo object
  Serial.begin(9600);
}

void loop() {
  for (pos = 95; pos >= 10; pos -= 1) { // goes from 95 degrees to 10 degrees
    myservo.write(pos);              // tell servo to go to position in variable 'pos'
    delay(40);                       // waits 40ms for the servo to reach the position
  }
  Serial.println("The door is open");
  delay(4000);
  
  ////////////////////////////////Check for resistance///////////////////////////////////
  currentTime  = 0;
  previousTime = 0;

  for (pos = 10; pos <= 95; pos += 1) { // goes from 10 degrees to 95 degrees
  previousTime = millis();
    // in steps of 1 degree
    myservo.write(pos);              // tell servo to go to position in variable 'pos'
    delay(30);                       // waits 30ms for the servo to reach the position
    
    currentTime = millis();  
    if (currentTime - previousTime >= 31) {
      for (int currentPos = pos; currentPos <= 10; currentPos -= 1) {
        myservo.write(currentPos);   // tell servo to go to position in variable 'currentPos'
        delay(30);
      }
      currentTime  = 0;
      previousTime = 0;
      delay(2000);
    }
  }

  delay(4000);
}

Thanks in advance!

You’ve been a member here for three years, and haven’t read this

Installation & Troubleshooting
For problems with Arduino itself, NOT your project

:o

Tonyboy:
Sorry, I can’t move my post to Programming Questions

I already asked a mod to do it for you.

TheMemberFormerlyKnownAsAWOL:
I already asked a mod to do it for you.

The OP retracted his post :slight_smile:

Tonyboy:
I found an example with 1-ohm, 5-watt metal film resistor here, but I am wondering if there is a possible solution with some code changes.

You have not told us what happened when you tried to replicate the YouTube demo.

...R

Hello,

It will probably work, I just wanted to see if anyone has already fixed that with code without a resistor.

BR
Anton

Tonyboy:
It will probably work, I just wanted to see if anyone has already fixed that with code without a resistor.

I don’t know what you had in mind when you wrote that. The resistor is essential in order to measure the current being drawn by the servo.

…R

There is no way to determine load on the servo with software, only.

I assume with "servo" you mean a standard RC-Servo.
This servo has three wires
minus plus signal towards the servo
Arduino-->-->-->-->-->-->--Servo

How the heck shall the Arduino know about the servo has hit a resistance??
There is nothing electrically or electronically there to do so.
There is no feedback at all from servo to Arduino.

So just with code it is impossible

One way to detect resistance is measureing the Servo's current
Another way would be to have a sensor that senses door fully opened.
Then you would check if sensor gives signal "door fully opened" after the normal open time
If the sensors gives no signal you can conclude door not fully opened.

Both ways have feedback from the servo towards the Arduino

A half-solution would be to shut off the power of the servo after openeing-time
but maybe the servo can't hold its position with power off

best regards Stefan

Tonyboy:
It will probably work, I just wanted to see if anyone has already fixed that with code without a resistor.

You could use a temperature sensor on the servo so that when its overloaded you detect that its starting to melt.
Or a smoke detector maybe.

That’s a good idea. I will try with a resistor tomorrow, thanks!
/Anton

IMHO letting the servo-motor get hot is a very bad idea.
It will take 2 to 5 minutes until the temperatur-rise is high enough to detect it with a temperature-sensor.
If I remember right you want to use this for an automatic cat-door.

So your cat has to stay 2 to 5 minutes "locked" in a half-open door? And if the servo burns through for hours if you are not at home?

If the cat can be hurt by a half open door you have to re-design the mechanic that keeping the cat catched in the doors mechanic can never happen!

The electronic-interface-effor will be the same as using a current-sensor. With a current-sensor you can stop the servo in less than a second.

best regards Stefan

StefanL38:
IMHO letting the servo-motor get hot is a very bad idea.

I think Reply #9 was an attempt at humour :slight_smile:

...R

Hello again,
It works with 1-ohm, 5-watt, (1R0) resistor and You can use it for different projects. Here comes a test example (see the code below).

#include <Adafruit_ILI9340.h>
#include <Servo.h>

Servo myservo;  // create servo object to control a servo
// twelve servo objects can be created on most boards

int pos;    // variable to store the servo position
int currentPos;
int sensorValue = 0;
int sensorPin = A0;
int treshold = 2;

void setup() {
  myservo.attach(9);  // attaches the servo on pin 9 to the servo object
  Serial.begin(9600);
  pinMode(INPUT, A0);
}

void loop() {
  for (pos = 10; pos <= 95; pos += 1) { // goes from 10 degrees to 95 degrees
    myservo.write(pos);              // tell servo to go to position in variable 'pos'
    sensorValue = analogRead(sensorPin);
    Serial.print("sensorValue: ");
    Serial.println(sensorValue);
    delay(30);                       // waits 30ms for the servo to reach the position
    
    if (sensorValue >= treshold) {
      Serial.println("Back to previous position");
      Serial.print("pos: ");
      Serial.println(pos);
      for (currentPos = pos; currentPos >= 11; currentPos -= 1) {
        myservo.write(currentPos);   // tell servo to go to position in variable 'currentPos'
        delay(30);
      }
      Serial.print("currentPos: ");
      Serial.println(currentPos);
      sensorValue = 0;
      delay(5000);
      break;
    }
  }
  delay(4000);
}

BR
Anton

    myservo.write(pos);              // tell servo to go to position in variable 'pos'
    sensorValue = analogRead(sensorPin);
    Serial.print("sensorValue: ");
    Serial.println(sensorValue);
    delay(30);                       // waits 30ms for the servo to reach the position

Im thinking there will be a current spile each time you move the servo. You should probably wait until the servo reaches its destination before checking the current:

    myservo.write(pos);              // tell servo to go to position in variable 'pos'
    delay(30);                       // waits 30ms for the servo to reach the position
    sensorValue = analogRead(sensorPin);
    Serial.print("sensorValue: ");
    Serial.println(sensorValue);