1

I was hoping to get some help on the fading led which I am working on.

For my project I need to have a led, which when it is placed next to a magnet, continuously shines, but as soon as it is taken away it has to fade out in a certain amount of time. So far I managed to write the code which detects when the light is taken away from the magnet and fades out, but when the magnet is nearby again, the led lights up and keeps shining, no matter if I take it away from the magnet or not. So how I could solve this? I tried to exit the loop function, but then this process happens only once, which is not what I want. I am also using reed switch to detect the magnet, but if you have other sensor suggestions, let me know. I'm including the code down here.

Thank you for your help in advance:)

int ledPin = 9;        
int brightness = 255; 
int fadeAmount = 5;
const int reedPin = 2;

void setup() {
  Serial.begin(9600);
  pinMode(ledPin, OUTPUT);
  pinMode(reedPin, INPUT_PULLUP);
}

void loop() {
  int proximity = digitalRead(reedPin);
  if (proximity == HIGH) {
    Serial.println("Switch opened");
    while (brightness >= 0) {
      analogWrite(ledPin, brightness);
      brightness = brightness - fadeAmount;
      delay(30);
      Serial.println(brightness);
    }
  }
  else {
    Serial.println("Switch closed");
    analogWrite(ledPin, brightness);
    Serial.println(brightness);
  }
}
1
  • 1
    First, please don't provide code as an image. Instead copy and paste the code as text into the question and format it correctly by selecting the code and clicking the {} button in the question editor
    – chrisl
    Nov 25, 2022 at 11:15

1 Answer 1

0

Your current problem probably comes from the fact, that you execute the fading loop, even if brightness is already zero, and that you don't reset it to zero after fading.

while(brightness >= 0){
   ...
   brightness = brightness - fadeAmount;
   ...
}

Imagine we are at the point, where brightness is 5. The while condition is true, since 5 > 0. Then we execute the code in the loop, setting brightness to 0. We again check the while condition. It is still true, since 0>=0. So after executing the code in the loop again, brightness is now -5. But analogWrite() only takes a 1 byte unsigned (!) integer, aka uint8_t, while int is a 2 byte signed (!) integer. So only the lower byte of that integer will be used and interpreted as unsigned. So -5 gets interpreted as 251, which you see as lighting up in full brightness.

Easy fix would be to set brightness to zero after the while loop:

brightness = 0;

That said, I would suggest a completely different route, which will make your code way more responsive, by using the non-blocking coding principle from the BlinkWithoutDelay example, that comes with the Arduino IDE.

As you did, I would use a global brightness and fadeAmount variable, but also one to hold a timestamp:

unsigned long timestamp=0;

Then in loop() we can first do the fading to zero by using the millis() function as a clock:

if(millis()-timestamp > 30){
    brightness = brightness - fadeAmount;
    if(brightness < 0) brightness = 0;
    timestamp = millis();
}

That will decrement the brightness variable to zero without blocking with a delay(). The speed can be changed by changing the number 30 to something different. This number has the unit milliseconds.

Then we can check for the reed switch and set brightness to 255, if it is activated:

if(!digitalRead(reedPin)){
    // reedPin is LOW
    brightness = 255;
}

So as long as the magnet is at the reed switch, this code will set brightness to 255.

And finally we need to write the value of brightness to the output pin:

analogWrite(ledPin, brightness);

So as a full code:

int ledPin = 9;
int reedPin = 2;

int brightness = 0;
int fadeAmount = 5;
unsigned long timestamp = 0;

void setup(){
    pinMode(ledPin, OUTPUT);
    pinMode(reedPin, INPUT_PULLUP);
}

void loop(){
    if(millis()-timestamp > 30){
        brightness = brightness - fadeAmount;
        if(brightness < 0) brightness = 0;
        timestamp = millis();
    }

    if(!digitalRead(reedPin)){
        // reedPin is LOW
        brightness = 255;
    }

    analogWrite(ledPin, brightness);
}

I've tested this with a normal button (currently no reed switch here). It should work as expected.

1
  • I tested it, it works. Thank you so much!
    – Igne
    Nov 25, 2022 at 12:04

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.