[SOLVED] PWM Trouble: Servo and Fading LED

Hello. I’m having trouble with a sketch that moves a servo and fades on an LED. The half of the script that detects the button press and moves the servo to position 180 (i.e. the “open” state in regard to my project) and turns off the LED works fine.

But when I press the button again to move the servo to position 0 (i.e. “closed”) and fade on the LED using the for loop, the servo moves like it should but the LED remains off for a moment and then simply turns on fully lit, without the fade effect.

I tried the sketch at www.youtube.com/watch?v=PHd9rTXz1iQ (code is in the comments section) and rewrote it to work the way I want it to for my project but I got the same result. The LED simply lights up after a short pause, there’s no slow fade on.

Thank you for any advice.

My sketch:

#include <Servo.h>

Servo servo;
const int btn = 2;
int btnVal = 0;
const int led = 9;

/* 
 * ASSUMING:
 * 0 = CLOSED
 * 180 = OPEN
*/ 

void setup()
{
  servo.attach(10);
  pinMode(btn, INPUT);
  pinMode(led, OUTPUT);
  servo.write(180);         // Start in open position
}

void loop()
{
 btnVal = digitalRead(btn);

 if(btnVal == HIGH)      // If button is pressed
 {
//  delay(100);
  if(servo.read() == 0)  // If servo is CLOSED, then open it
  {
    analogWrite(led, 0);
    servo.write(180);
    delay(1000);
  } else {               // Else servo is OPEN, so close it
    servo.write(0);
    delay(400);          // Wait for servo to close before lighting led
    
    for(int fadeValue = 0 ; fadeValue <= 255; fadeValue +=5) {    // LED fade on
      // sets the value (range from 0 to 255):
      analogWrite(led, fadeValue);        
      // wait for 30 milliseconds to see the dimming effect    
      delay(30);                            
    }
    
    delay(1000);
  }
 } 
}

all that blocking code will affect your response to a button press.

try using a state change detection on the button, rather than just looking for HIGH.

untested:

#include <Servo.h>

Servo servo;
const int btn = 2;
int lastButtonVal = 0;
const int led = 9;

/* 
 * ASSUMING:
 * 0 = CLOSED
 * 180 = OPEN
 */

void setup()
{
  servo.attach(10);
  pinMode(btn, INPUT);
  pinMode(led, OUTPUT);
  servo.write(180);         // Start in open position
}

void loop()
{
  int btnVal = digitalRead(btn);
  if(btnVal == HIGH && lastButtonVal == LOW)      // If button is pressed
  {
    //  delay(100);
    if(servo.read() == 0)  // If servo is CLOSED, then open it
    {
      analogWrite(led, 0);
      servo.write(180);
      delay(1000);
    } 
    else 
    { 
      servo.write(0);
      delay(400);          // Wait for servo to close before lighting led
      for(int fadeValue = 0 ; fadeValue <= 255; fadeValue +=5) {    // LED fade on
        analogWrite(led, fadeValue);        
        delay(30);                            
      }
      delay(1000);
    }
  } 
  lastButtonVal = btnVal;
}

Thank you for your help Bulldog but I tried your edited sketch and I still have the same problem: the LED will not fade on.

Merely commenting out servo.attach(10); fixes the problem and the LED fades on like I want. But of course the servo no longer moves.

Jeremy

Hmm, I found something strange. If I change the value of the iteration in the for loop from fadeValue +=5 to fadeValue +=4 the LED won't even light up.

EDIT:

Nevermind this post. I think the iteration value has to be a factor of 255. When I changed the value to 3 (255/3 = 85) the LED worked again... but still no fading effect.

I don't understand why you can't remember what position you sent the servo to last time. Asking the servo class to remember that for you is silly.

The servo library uses a timer. PWM uses timers. When you use a servo, PWM on some pins is disabled (because the required timer is not available). One the UNO and other 328 based Arduinos, PWM on pins 9 and 10 goes first. Try another PWM pin.

Have you tried moving the servo a step at a time along with the fading

For instance.

Instead of this

servo.write(0);
delay(400);          // Wait for servo to close before lighting led
  for(int fadeValue = 0 ; fadeValue <= 255; fadeValue +=5) {    // LED fade on
     analogWrite(led, fadeValue);        
     delay(30);                            
    }

Try this

    for(int servoPos=180;servoPos>-1;servoPos--)
      {
       int fadeValue=map(servoPos,180,0,0,255);
       servo.write(servoPos);
       analogWrite(led,fadeValue);
       delay(30); 
      }

PaulS: One the UNO and other 328 based Arduinos, PWM on pins 9 and 10 goes first. Try another PWM pin.

PaulS was right. I moved the LED from pin 9 to pin 3 and now it works. Thank you everyone for your help.