Possible memory leak somewhere?

I have a device which uses:

  1. Real time module
  2. PIR Sensor
  3. LED Strip

Its function is simple:
IF time is between 20PM and 6AM AND Infrared sensor detects movement THEN light up LED strip.

And it works great - for like 40 minutes. After that it stops working until I press the reset button on the Arduino. At which point it works again! I ruled out the electronics because I rebuilt it on a breadboard with a different Arduino.

That makes me believe the issue is the code. It feels like a memory leak to me. I can't spot one though. Does anyone maybe see one?

#include <FastLED.h>
#include <Wire.h>  
#include <RTClib.h> 

RTC_DS3231 rtc; 

#define LED_PIN     8
#define NUM_LEDS    60
int pirPin = 2; // Input for HC-S501

CRGB leds[NUM_LEDS];


int pirValue; // Place to store read PIR Value


void setup() {
  Serial.begin(9600);
  pinMode(pirPin, INPUT);

  FastLED.addLeds<WS2812, LED_PIN, GRB>(leds, NUM_LEDS);
  rtc.begin();
  rtc.adjust(DateTime(F(__DATE__), F(__TIME__)));//auto update from computer time

}

void loop() {
  pirValue = digitalRead(pirPin);

  DateTime nowTime = rtc.now();

  Serial.print(nowTime.hour());
  Serial.print("pir:/");
  Serial.print(pirValue);
  

  if (pirValue != 0) {
    if (nowTime.hour() >= 20 || nowTime.hour() <= 6) {
      for (int i = 0; i < NUM_LEDS; i++) {
        leds[i] = CRGB(127, 73, 20);
      }
      FastLED.show();
      delay(15000);
    }
  } else {
   FastLED.clear();
   FastLED.show();
  }
}

Schematic:

What is the nature of the signal from the PIR? I'm going to guess it's just a contact and you don't have a pull up / down resistor.

Please post a schematic and some clear photos of your project.

Thank you

I'm not following your question about the signal from the PIR. I do not have a pull up or pull down resistor. The component is an HC-SR501 if that helps.

I've now added an image of the schematic. I can't provide photos of the physical components themselves at this moment however, but I had recreated everything from scratch following the schematic with the same results.

Slow the loop down ... delay(100);

I can see how that would help reduce its workload, but do you believe that would solve the issue?
If it's a memory leak it would definitely make the issue appear a lot more slowly I suppose.

Based on what? Where does your code do any dynamic memory allocation?

How much would it cost to try it?

The only indication I have is its behaviour, but I'll be clear in that I don't know if it's a memory leak.
It functions for a period of time, and then stops until it's reset. The period of time in which it functions is consistent.

Grab Adafruit's FreeMemory function and see how much you have.

1 Like

It wouldn't, and it's a change I'll try, but I'm trying to understand why the delay is being proposed.

I don't know how else to ask it more clearly, what does the PIR output? Is it a relay contact? A transistor? MOSFET? Open collector / drain? What exactly? What does the datasheet say?

The PIR gives a digital pulse - high 3.3v when triggered and low 0v when idle.
I'm trying to wrap my head around what is meant by output in this context as I'm new to electronics, so thanks for bearing with me.

When I read the value through the following I'll just get a 0/1 based on state.

pirValue = digitalRead(pirPin);

How is all this powered?

There are 3 changes I would make:

  1. You read the PIR value at the beginning of loop() and store it in a variable that is used for the rest of that loop. This is good.

    Do the same for the hour: nowHour = nowTime.hour();

  2. The PIR sensor can be set to output HIGH for 2.5 - 30 seconds so you don't need the delay() in your sketch.

    From the Datasheet:

Also set the Trigger to H to keep the PIR Output HIGH until 15sec. after the LAST detection of movement.
Or set the Trigger to L to keep PIR Output HIGH for 15sec. after the FIRST detection of movement.

  1. FastLED.clear(); is not doing what you think. Turn off the LED's the same way you turned them on:
for (int i = 0; i < NUM_LEDS; i++) {
        leds[i] = CRGB(0, 0, 0);  // turn off LED's
      }

Full code w/ changes:

#include <FastLED.h>
#include <Wire.h>  
#include <RTClib.h> 

RTC_DS3231 rtc; 

#define LED_PIN     8
#define NUM_LEDS    60
int pirPin = 2; // Input for HC-S501

CRGB leds[NUM_LEDS];


int pirValue; // Place to store read PIR Value
int nowHour; // store Hour;


void setup() {
  Serial.begin(9600);
  pinMode(pirPin, INPUT);

  FastLED.addLeds<WS2812, LED_PIN, GRB>(leds, NUM_LEDS);
  rtc.begin();
  rtc.adjust(DateTime(F(__DATE__), F(__TIME__)));//auto update from computer time

}

void loop() {
  DateTime nowTime = rtc.now();
  
  nowHour  = nowTime.hour();
  pirValue = digitalRead(pirPin);
  
  Serial.print(nowHour);
  Serial.print("pir:/");
  Serial.print(pirValue);
  

  if (pirValue != 0) {
    if (nowHour >= 20 || nowHour <= 6) {
      for (int i = 0; i < NUM_LEDS; i++) {
        leds[i] = CRGB(127, 73, 20);
      }
      FastLED.show();
      // delay(15000); // This delay is not needed because the PIR sensor can take care of this for us
    }
  } else {
   for (int i = 0; i < NUM_LEDS; i++) {
        leds[i] = CRGB(0, 0, 0); // turn off LED's
      }
   FastLED.show();
  }
}

Sadly, the class DateTime in RTClib.h makes use of String objects.

String timestamp(timestampOpt opt = TIMESTAMP_FULL) const;

You might try moving the declaration of nowTime out of loop() and make it global instead (so it is executed only once).

DateTime nowTime = rtc.now();

What happens when it "stops working"? Do the Hour and PIR reading continue to print but the LEDs don't activate? Or, does all apparent activity stop?

From what I can see, it's used by only one class function, and OP isn't calling that one:

 String timestamp(timestampOpt opt = TIMESTAMP_FULL) const;

OK, thanks.
The only thing I can see from what you've showed is there should be a capacitor across the power of the LED strip close to where it's powered. Maybe 470μF or something, exact value not important. The layout and quality of the wiring might have an effect, which is why I want the photos. I can't see anything wrong with the code but there are other people helping you who are better than me at spotting code problems.

@gfvalvo asked what happens when it stops working, that might be useful information.

What do the serial prints show when it stops working?

Just checking here ... do you realize that comment is incorrect? The statement does not do that. Rather, every time your Arduino board is powered up or reset, it sets the RTC to the time when your program was compiled. Not the current time and it involves no data transfer with the PC.

So I'll ask again, what do the Serial.print() statements of your variables show when the program "stops working"?

I have a 5V 20A dc power supply.

Thanks for this, that’s very helpful.

Makes sense, and I’ll update accordingly.

Wasn’t aware of that, hadn’t seen mention of it in the strip‘s manuals but I’ll add one. Thanks.

That is very good to know, and that explains a different behavior I experienced once, thanks for the good spot.

I’ll be monitoring that when I get back to the project, at the time of writing this post I didn’t have a device I could use to monitor the output at the location.