Servo not holding position

I am working on a project where I have to close a window with a servo when the CO2 value is too high. When the servo opens it has enough power and it stays in this position but when the servo closes it doesn't give enough power and it won't stay in position. Anyone have an idea?

#include "SCD30.h"
#include <Servo.h>
Servo myservo;
#if defined(ARDUINO_ARCH_AVR)
#pragma message("Defined architecture for ARDUINO_ARCH_AVR.")
#define SERIAL Serial
#elif defined(ARDUINO_ARCH_SAM)
#pragma message("Defined architecture for ARDUINO_ARCH_SAM.")
#define SERIAL SerialUSB
#elif defined(ARDUINO_ARCH_SAMD)
#pragma message("Defined architecture for ARDUINO_ARCH_SAMD.")
#define SERIAL SerialUSB
#elif defined(ARDUINO_ARCH_STM32F4)
#pragma message("Defined architecture for ARDUINO_ARCH_STM32F4.")
#define SERIAL SerialUSB
#else
#pragma message("Not found any architecture.")
#define SERIAL Serial
#endif

#include <Wire.h>
#include "rgb_lcd.h"
// KNOPPEN
const int automatisch = 6;
const int manueel = 5;// the number of the pushbutton pin
const int opentoeknop = 2;
byte openen = HIGH;
byte sluiten = LOW;


//LEDS
const int ledPinBlauw = 4;
const int ledPinGroen =  3;

// LCD scherm
rgb_lcd lcd;
const int colorR = 50;
const int colorG = 140;
const int colorB = 0;

// variablen
int ppmmax = 900;
int joeri = 0;
int buttonState = 0;
int buttonState1 = 0;
int buttonState2 = 0;
int lastButtonState = 0;
int buttonPushCounter = 0;
int pos = 0;
int waarde=0;
int servohoek=0;

void setup() {
  // initialize the LED pin as an output:
  pinMode(ledPinGroen, OUTPUT);
  // initialize the pushbutton pin as an input:
  pinMode(automatisch, INPUT);
  pinMode(manueel, INPUT);
  pinMode(opentoeknop, INPUT);

  pinMode(ledPinBlauw, OUTPUT);
  digitalWrite(ledPinBlauw, LOW);
  digitalWrite(ledPinGroen, LOW);


  lcd.begin(16, 2);
  lcd.setRGB(colorR, colorG, colorB);
  lcd.setCursor(0, 0);
  lcd.print("A: Automatisch");
  lcd.setCursor(0, 1);
  lcd.print("B: Manueel");
  Wire.begin();
  SERIAL.begin(115200);
  SERIAL.println("SCD30 Raw Data");
  scd30.initialize();

  myservo.attach(8);


}

void loop() {
  while (joeri == 0) {
    buttonState = digitalRead(automatisch);
    buttonState1 = digitalRead(manueel);
    if (buttonState == HIGH) {
      // turn LED on:
      lcd.setCursor(0, 0);
      lcd.print("U kiest voor    ");
      lcd.setCursor(0, 1);
      lcd.print("automatisch       ");
      joeri = joeri + 1;
      delay(2000);
      digitalWrite(ledPinGroen, HIGH);
    }


    // check if the pushbutton is pressed. If it is, the buttonState is HIGH:
    if (buttonState1 == HIGH) {
      // turn LED on:
      lcd.setCursor(0, 0);
      lcd.print("U kiest voor     ");
      lcd.setCursor(0, 1);
      lcd.print("manueel       ");
      joeri = joeri + 1;
      delay(2000);
      digitalWrite(ledPinGroen, HIGH);
    }

  }
  while (joeri >= 1) {
    float result[3] = {0};

    while (buttonState == HIGH) {
      scd30.getCarbonDioxideConcentration(result);
      SERIAL.print("Carbon Dioxide Concentration is: ");
      SERIAL.print(result[0]);
      SERIAL.println(" ppm");
      SERIAL.println(" ");
      SERIAL.print("Temperature = ");
      SERIAL.print(result[1]);
      SERIAL.println(" ℃");
      SERIAL.println(" ");
      SERIAL.print("Humidity = ");
      SERIAL.print(result[2]);
      SERIAL.println(" %");
      SERIAL.println(" ");
      SERIAL.println(" ");
      SERIAL.println(" ");
      lcd.setCursor(0, 0);
      lcd.print("CO2: ");
      lcd.print(result[0]);
      lcd.print(" ppm");
      lcd.setCursor(0, 1);
      lcd.print("Temp: ");
      lcd.print(result[1]);
      lcd.print(" C");
      buttonState = HIGH;
      delay(5000);
      while (result[0] >= ppmmax) {
        scd30.getCarbonDioxideConcentration(result);
        SERIAL.print("Carbon Dioxide Concentration is: ");
        SERIAL.print(result[0]);
        SERIAL.println(" ppm");
        SERIAL.println(" ");
        SERIAL.print("Temperature = ");
        SERIAL.print(result[1]);
        SERIAL.println(" ℃");
        SERIAL.println(" ");
        SERIAL.print("Humidity = ");
        SERIAL.print(result[2]);
        SERIAL.println(" %");
        SERIAL.println(" ");
        SERIAL.println(" ");
        SERIAL.println(" ");
        lcd.setCursor(0, 0);
        lcd.print("CO2: ");
        lcd.print(result[0]);
        lcd.print(" ppm");
        lcd.setCursor(0, 1);
        lcd.print("Temp: ");
        lcd.print(result[1]);
        lcd.print(" C");
        
        if (servohoek == 0) {
          for (pos = 0; pos <= 45; pos += 1) {
            // goes from 0 degrees to 180 degrees
            // in steps of 1 degree
            myservo.write(pos);              // tell servo to go to position in variable 'pos'
            delay(15);
            
          }
          servohoek=90;
          Serial.println("open");
        }
        digitalWrite(ledPinBlauw, HIGH);
        delay(5000);



      }

      scd30.getCarbonDioxideConcentration(result);
      SERIAL.print("Carbon Dioxide Concentration is: ");
      SERIAL.print(result[0]);
      SERIAL.println(" ppm");
      SERIAL.println(" ");
      SERIAL.print("Temperature = ");
      SERIAL.print(result[1]);
      SERIAL.println(" ℃");
      SERIAL.println(" ");
      SERIAL.print("Humidity = ");
      SERIAL.print(result[2]);
      SERIAL.println(" %");
      SERIAL.println(" ");
      SERIAL.println(" ");
      SERIAL.println(" ");
      lcd.setCursor(0, 0);
      lcd.print("CO2: ");
      lcd.print(result[0]);
      lcd.print(" ppm");
      lcd.setCursor(0, 1);
      lcd.print("Temp: ");
      lcd.print(result[1]);
      lcd.print(" C");
       if (servohoek == 90) {
          for (pos = 45; pos >= 0; pos -= 1) {
            // goes from 0 degrees to 180 degrees
            // in steps of 1 degree
            myservo.write(pos); 
           
            // tell servo to go to position in variable 'pos'
            delay(15);
            
          }
          servohoek=0;
          Serial.println("toe");
        }
      digitalWrite(ledPinBlauw, LOW);
      delay(5000);

    }
    while (buttonState1 == HIGH) {
      buttonState2 = digitalRead(automatisch);

      // compare the buttonState to its previous state
      if (buttonState2 != lastButtonState) {
        // if the state has changed, increment the counter
        if (buttonState2 == HIGH) {
          // if the current state is HIGH then the button went from off to on:
          buttonPushCounter++;
          Serial.println("on");
          Serial.print("number of button pushes: ");
          Serial.println(buttonPushCounter);
        } else {
          // if the current state is LOW then the button went from on to off:
          Serial.println("off");
        }
        // Delay a little bit to avoid bouncing
        delay(50);
      }

      lastButtonState = buttonState2;



      if (buttonPushCounter % 2 == 0) {
        digitalWrite(ledPinBlauw, HIGH);
        if (servohoek == 0) {
          for (pos = 0; pos <= 90; pos += 1) {
            // goes from 0 degrees to 180 degrees
            // in steps of 1 degree
            myservo.write(pos);              // tell servo to go to position in variable 'pos'
            delay(15);
            
          }
          servohoek=90;
          Serial.println("open");
        }
        else {
          scd30.getCarbonDioxideConcentration(result);
          SERIAL.print("Carbon Dioxide Concentration is: ");
          SERIAL.print(result[0]);
          SERIAL.println(" ppm");
          SERIAL.println(" ");
          SERIAL.print("Temperature = ");
          SERIAL.print(result[1]);
          SERIAL.println(" ℃");
          SERIAL.println(" ");
          SERIAL.print("Humidity = ");
          SERIAL.print(result[2]);
          SERIAL.println(" %");
          SERIAL.println(" ");
          SERIAL.println(" ");
          SERIAL.println(" ");
          lcd.setCursor(0, 0);
          lcd.print("CO2: ");
          lcd.print(result[0]);
          lcd.print(" ppm");
          lcd.setCursor(0, 1);
          lcd.print("Temp: ");
          lcd.print(result[1]);
          lcd.print(" C");

          delay(2000);
        }
      } 
      else {
        digitalWrite(ledPinBlauw, LOW);
       
        if (servohoek == 90) {
          for (pos = 90; pos >= 0; pos -= 1) {
            // goes from 0 degrees to 180 degrees
            // in steps of 1 degree
            myservo.write(pos); 
           
            // tell servo to go to position in variable 'pos'
            delay(15);
            
          }
          servohoek=0;
          Serial.println("toe");
        }
        else {
            digitalWrite(ledPinBlauw,LOW);
 
  
  
          scd30.getCarbonDioxideConcentration(result);
          SERIAL.print("Carbon Dioxide Concentration is: ");
          SERIAL.print(result[0]);
          SERIAL.println(" ppm");
          SERIAL.println(" ");
          SERIAL.print("Temperature = ");
          SERIAL.print(result[1]);
          SERIAL.println(" ℃");
          SERIAL.println(" ");
          SERIAL.print("Humidity = ");
          SERIAL.print(result[2]);
          SERIAL.println(" %");
          SERIAL.println(" ");
          SERIAL.println(" ");
          SERIAL.println(" ");
          lcd.setCursor(0, 0);
          lcd.print("CO2: ");
          lcd.print(result[0]);
          lcd.print(" ppm");
          lcd.setCursor(0, 1);
          lcd.print("Temp: ");
          lcd.print(result[1]);
          lcd.print(" C");

          delay(2000);
        }
      }
    }
  }

}

Post a schematic of the wiring. Include all components, their part numbers and/or values and all power supplies.

1 Like

How heavy is the window?

I haven't tested on the window yet but I can hold the servo by hand when it's closing.

What is the servo power supply voltage and current capability?

Post the servo data sheet.

1 Like

I only put the servo in the schematic because the rest is not needed with this problem I think


The servo is not on the maximum output voltage but I find it strange that it opens and closes.

2 Likes

Well, there's your problem. The Uno is not a power supply. The USB can provide up to about 500mA. Your servo needs 1A or more to move. Try it with a 4 AA cell battery pack or a 5V phone charger that is capable of at least 1A per servo.

1 Like

Thanks, i will try!

Yeah, I've already tried it with 4AA batteries but it didn't work. But as I see in the picture of StefanL38 I have to connect the ground together.

it runs on the batteries but the servo still won't hold its position. So I mean I can move the servo without any effort when it's closed. When the window opens I can't stop the servo but when closing I can stop it.

I did a quick look at your code. I guess your code can be greatly simplified

please write a description of the wanted functionality. Use everyday normal words for this description. With a switch-case-break state-machine the code can be greatly simplified.

A servo is a servo. And usually a servo does not care at all at which position you set it to.
It should hold its position regardless of what this position is.

Except maybe the pulse-length of the servo-signal is too short or too long. But you have nothing in your code that would change minpulswidth / maxpulsewidth

Did you measure what current this servo is pulling?

You can add serial debug-output to your code to make visible what values variable "pos" does have

best regards Stefan

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