-1

I am having trouble with part of my code.

I am working on a program, that using a sensor and a dfplayer, should play a track and while the track is being played, a LED should be turned on with a fade effect, until the track stops playing.

I have the function sensorActivated() that is executed on the main loop.

4
  • It only works if I call fadingLED() ... what does that mean? ... how is it failing?
    – jsotola
    Mar 21 at 19:33
  • please don't say when certain conditions are given ... list the conditions instead
    – jsotola
    Mar 22 at 1:30
  • Are the messages DFplayer status: and so on printed?
    – Nick Gammon
    Mar 22 at 2:58
  • I will edit the question to be more clear, thanks. Mar 22 at 8:51

2 Answers 2

0

Here's a possible solution, a proof-of-concept on how it might be done. One of the issues you've got is that you are using delay() in a way that stops the code, without letting other things happen. Check out the Arduino 'BlinkWithoutDelay'. Note that if you start the intensity less than 20, with an increment of 4, you will add 4, but then go back to the original number. You might want to take a look at that and make sure you can't get to that situation.

You always need to call the function in the loop, but you only need to do it when you want it to be executed. This program could be improved (get rid of the globals, use static variables), but that is something you can fix readily.

This code added a bit of serial output, so you can use the 'serial plotter' in the IDE to see how the 'glow' bit goes on and off, and to see the varying intensity in your LED.

// Have a glowing effect, but only when the glow bit is true
// time out

#define LED 13

unsigned long currenttime;
unsigned long currenttimeold;
unsigned long lastledtime;
unsigned long printold;
bool glow = false;
int brightness = 60;
int counter;
int fadeAmount = 4;

void setup() {
  // put your setup code here, to run once:
  Serial.begin(9600);
}

void loop() {
  // put your main code here, to run repeatedly:

  currenttime=millis();
  
  // Every 100 ms, add to a counter
  // When this hits 50, invert the glow bit
  if ((currenttime - currenttimeold) > 100)
  {
    currenttimeold = currenttime;
    counter = counter + 1;
    if (counter > 50)
    {
      glow = !glow;
      counter = 0;
    }
  }

  // If glow bit is on, fade the LED
  // otherwise shut it off
  if (glow)
  {
    fadingLED();
  }
  else
  {
    analogWrite(LED, 0);
  }

  if ((currenttime - printold) > 50)
  {
    printold=currenttime;
    // Serial.print(millis());
    // Serial.print(",");
    Serial.print(glow * 100);
    Serial.print(",");
    Serial.print(brightness);
    Serial.print("\n");
  }

}


void fadingLED() {
  //Lo del led
  analogWrite(LED, brightness);

  if ((millis() - lastledtime) > 60)
  {
    lastledtime = millis();
    // change the brightness for next time through the loop:
    brightness = brightness + fadeAmount;

    // reverse the direction of the fading at the ends of the fade:
    if (brightness <= 20 || brightness >= 100) {
      fadeAmount = -fadeAmount;
    }
  }

}
0

I saw your newer comments and I played around with this today using an UNO and this PIR. The code below, while lacking any semblance of elegance, does work. When it starts, it sets the volume and then waits for activation of the motion detector. It then plays a "random" track while pulsing the LED. The LED is pulsing only while a track is playing and is extinguished when no track is playing. Note how I am using ".isPlaying()".

Hope it helps.

#include <DFPlayerMini_Fast.h>
#include <SoftwareSerial.h>

SoftwareSerial MySerial(10, 11); // RX, TX
DFPlayerMini_Fast MyMP3;

    #define PIR 8        // PIR input pin
    #define LED 9        // led pin 
    #define pulseDelay 5 // milliseconds between LED change
    
    int brightness = 0;  // PWM level for LED
    int fadeAmount = 5;  // how many points to fade the LED by
    int volume = 25;     // Player initial volume
    int nFiles = 15;     // number of mp3 files on sd card
    
    void setup() {
      analogWrite(LED, brightness);
      randomSeed(analogRead(5));
      Serial.begin(9600);
      MySerial.begin(9600);
      MyMP3.begin(MySerial, false);
      MyMP3.stop();
      Serial.print("Setting volume to ");
      Serial.println(volume);
      MyMP3.volume(volume);
    }
    
    void loop() {
      sensorActivated();
      fadingLED();
    }
    
    void fadingLED() {
      static unsigned long timer = millis();
    
      if (MyMP3.isPlaying()) {
        if (millis() - timer > pulseDelay) {
          timer = millis();
          analogWrite(LED, brightness);
          brightness = brightness + fadeAmount;
          if (brightness == 0 || brightness >= 255) {
            fadeAmount = -fadeAmount;
          }
        }
      }
    }
    
    void sensorActivated() {
      if ( (digitalRead(PIR) == HIGH) && (!MyMP3.isPlaying()) )
      {
        Serial.println("Sensor Activated");
        Serial.print("Random track being played: ");
        int randomInt = random(1, nFiles + 1);
        Serial.println(randomInt);
        MyMP3.play(randomInt);
      }
      else {
        if (!MyMP3.isPlaying())
        {
          if (brightness) {
            brightness = 0;
            analogWrite(LED, brightness);
          }
        }
      }
    }

==================

You can make this a bit easier if you clearly say what you want the effect to be. For example, when the DFP is NOT playing (the track is finished) pulse the LED UNTIL there is motion which causes another track to play.

Or maybe, pulse the LED as long as the the DFP is playing and turn the LED off when the DFP is not playing.

What you have written is: *I want to execute fadingLED(); only with the condition:

if(pirSensor == HIGH && myDFPlayer.isPlaying()!=1) I know my code is wrong. What would be the best approach to execute fadingLED() with the condition (pirSensor == HIGH && myDFPlayer.isPlaying()!=1) ???*

The problem that I see is that when the condition, if(pirSensor == HIGH && myDFPlayer.isPlaying()!=1) is true, you execute code to randomly select another track and start playing again. This would occur very quickly, so, myDFPlayer.isPlaying() will change and you will never be able to see the the pulsing LED.

I think you have it written incorrectly.

I will ASSUME that when the PIR sensor is LOW, it indicates motion and when myDFP.isPlaying()!=1 indicates that it is NOT playing. When you detect motion AND the DFP is not playing, you want to start another track playing.

So, change the line in sensorActivated() to if(pirSensor == LOW && myDFPlayer.isPlaying()!=1)

Note: if I have the PIR sensor output wrong, then leave it as if(pirSensor == HIGH && myDFPlayer.isPlaying()!=1) but read the rest, so you see what I am getting at because you can't use that same conditional test in the fadingLED() functions.

Now, when it is not playing and you detect motion, another track will start playing.

Replace "fadingLED();" in sensorActivated to:

brightness=20; analogWrite(LED, brightness);

It becomes:

    void sensorActivated() {

  // DFPlayerMini_Fast.h has a built-in function, "player.isPlaying()", that returns a boolean based on if the module is playing a song currently or not.
  int pirSensor = digitalRead(SENSORPIN);

  if (pirSensor == HIGH && myDFPlayer.isPlaying() != 1)
  {
    Serial.println("DFplayer status: ");
    Serial.println(myDFPlayer.isPlaying());
    Serial.println("Sensor Activated");
    Serial.println("DFPlayer Working...");
    Serial.println("Random track being played: ");
    randomInt = random(3, 8);
    Serial.println(randomInt);
    myDFPlayer.play(randomInt);
    brightness = 20;
    analogWrite(LED, brightness);
    // you may need to wait here until myDFPlayer.isPlaying() changes values

  }
}

Now while it is playing, the LED is dim (it can be modified to be off later);

Modify fadingLED to this:

void fadingLED() {

  static unsigned long timer = millis();

  if (myDFPlayer.isPlaying() != 1)) {
    if (millis() - timer > pulseDelay) {
      timer = millis();
      analogWrite(LED, brightness);
      // change the brightness for next time through the loop:
      brightness = brightness + fadeAmount;
      // reverse the direction of the fading at the ends of the fade:
      if (brightness == 20 || brightness >= 100) {
        fadeAmount = -fadeAmount;
      }
    }
  }
}

This function does not need a blocking call (e.g., delay() which sits there until the time has elapsed). Now, whenever the DFP is NOT playing, the LED will be pulsing.

In the beginning of the code use:

#define LED 9     //  led a pin 9
#define pulseDelay 60    // millis
int brightness = 20;  // how bright the LED is
int fadeAmount = 5;  // how many points to fade the LED by

Notice that I added pulseDelay and defined it as 60, which is the millisecond delay you had been using.

Finally, use:

void loop() {
  sensorActivated();
  fadingLED();
}

Additionally, you're using analog write values from 20-100. Remember, this is not a percentage. The range is 0-255. You can modify this easily.

Even if you want it flashing while playing, there is, hopefully, enough in the answer that you might find helpful

3
  • Hello. I edited my question, trying to be clear. I checked your solution and calling fadingLED(); from the main loop, makes the led blink all the time. I want the LED to have a fading effect, but only while playing, and to stay off while dfp is not playing. For some reason, and I don't know why (looks weird, honestly), while playing, I should use myDFPlayer.isPlaying() != 1) instead of myDFPlayer.isPlaying() == 1), and when it is not playing, myDFPlayer.isPlaying() == 0) Mar 23 at 17:05
  • The latest code (a complete program) that I posted on the 22nd works well for me. Only flashes when a track is playing. Turns off when not playing. The PIR activates a random track and starts play. Listened to a bunch of tunes for several hours. Sorry, but I am not sure why you are still having problems.
    – DrG
    Mar 26 at 20:10
  • There is something I'm not sure I understand totally, perhaps you can help me with that. About myDFPlayer.isPlaying() status: Wont it be myDFPlayer.isPlaying() != 1 and isPlaying()==0 the same thing? If status is equal to 0, status is different than 1, so it would give the same result, right? Thank you so much! Mar 28 at 22:04

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