Arduino Sleep mode with PIR interrupt to control neopixels

Hi there,
I'm currently trying to use an Arduino UNO that will be powered off a battery pack therefore I am utilising the sleep function with a PIR motion sensor to interrupt the sleep and wake it up whilst motion is detected it will do a neopixel display and then turn off when motion is no longer detected.
my current code is as follows and results in the Arduino stuttering the neopixels rather than making them flow, it also isn't turning them off when motion is no longer detected.

#include "LowPower.h"
#include "FastLED.h"
#if FASTLED_VERSION < 3001000
#error "Requires FastLED 3.1 or later; check github for latest code."
#endif
#define DATA_PIN    8
//#define CLK_PIN   4
#define LED_TYPE    WS2811
#define COLOR_ORDER GRB
#define NUM_LEDS    200
#define BRIGHTNESS  100

CRGB leds[NUM_LEDS];

const int wakeUpPin = 2;

void wakeUp()
{
  detachInterrupt(digitalPinToInterrupt(wakeUpPin));
  
}

void setup()
{
  Serial.begin(9600);
  pinMode(wakeUpPin, INPUT);
  FastLED.addLeds<LED_TYPE,DATA_PIN,COLOR_ORDER>(leds, NUM_LEDS)
    .setCorrection(TypicalLEDStrip)
    .setDither(BRIGHTNESS < 255);

  // set master brightness control
  FastLED.setBrightness(BRIGHTNESS);  
}

void loop()
{
  Serial.println("Going to Sleep");
  delay(1000);
  attachInterrupt(digitalPinToInterrupt(wakeUpPin), wakeUp, RISING);
  LowPower.powerDown(SLEEP_FOREVER, ADC_OFF, BOD_OFF);

  Serial.println("Woke up");
  delay(1000);
  static uint16_t sPseudotime = 0;
  static uint16_t sLastMillis = 0;
  static uint16_t sHue16 = 0;
 
  uint8_t sat8 = beatsin88( 87, 220, 250);
  uint8_t brightdepth = beatsin88( 341, 96, 224);
  uint16_t brightnessthetainc16 = beatsin88( 203, (25 * 256), (40 * 256));
  uint8_t msmultiplier = beatsin88(147, 23, 60);

  uint16_t hue16 = sHue16;//gHue * 256;
  uint16_t hueinc16 = beatsin88(113, 1, 3000);
  
  uint16_t ms = millis();
  uint16_t deltams = ms - sLastMillis ;
  sLastMillis  = ms;
  sPseudotime += deltams * msmultiplier;
  sHue16 += deltams * beatsin88( 400, 5,9);
  uint16_t brightnesstheta16 = sPseudotime;
  
  for( uint16_t i = 0 ; i < NUM_LEDS; i++) {
    hue16 += hueinc16;
    uint8_t hue8 = hue16 / 256;

    brightnesstheta16  += brightnessthetainc16;
    uint16_t b16 = sin16( brightnesstheta16  ) + 32768;

    uint16_t bri16 = (uint32_t)((uint32_t)b16 * (uint32_t)b16) / 65536;
    uint8_t bri8 = (uint32_t)(((uint32_t)bri16) * brightdepth) / 65536;
    bri8 += (255 - brightdepth);
    
    CRGB newcolor = CHSV( hue8, sat8, bri8);
    
    uint16_t pixelnumber = i;
    pixelnumber = (NUM_LEDS-1) - pixelnumber;
    
    nblend( leds[pixelnumber], newcolor, 64);
  }
}

Please post a link to the datasheet of that PIR sensor.

Hi thanks for helping the one I’m using is the HC sr501 on the “H” mode

It was a sales site but searching a real datasheet was found.
The output should be possible to use as wake up signal.
I don't see the code contains any turn off.

I was thinking that it may be possible to utilise when the output is LOW then the Arduino would sleep and when it is HIGH when motion is detected it would turn on and then when the signal stops again it would go back to sleep?

My concern was whether that output needed a pullup or a pulldown resistor.
Yes. Only check the signal in loop. When the signal goes inactive, turn off the LEDs and go asleep.

should I make the lighting into a sub routine? but then how does it know when to turn off if its running a different loop?

In C language there are "functions"....
If You use either "lights on" or "lights off" it could be a good idea.

operateLED(true);// turn on LEDs
.
.
operatedLED(false); turn off LEDs
void operateLED( bool OnorOff )
{
 .
.
.
.}

Hi again I've tried adding it but judging by how it isn't working I'm assuming I've used it wrong...

```cpp
#include "LowPower.h"
#include "FastLED.h"
#if FASTLED_VERSION < 3001000
#error "Requires FastLED 3.1 or later; check github for latest code."
#endif
#define DATA_PIN    8
//#define CLK_PIN   4
#define LED_TYPE    WS2811
#define COLOR_ORDER GRB
#define NUM_LEDS    200
#define BRIGHTNESS  100

CRGB leds[NUM_LEDS];

const int wakeUpPin = 2;

void wakeUp()
{
  detachInterrupt(digitalPinToInterrupt(wakeUpPin));
  
}

void setup()
{
  Serial.begin(9600);
  pinMode(wakeUpPin, INPUT);
  FastLED.addLeds<LED_TYPE,DATA_PIN,COLOR_ORDER>(leds, NUM_LEDS)
    .setCorrection(TypicalLEDStrip)
    .setDither(BRIGHTNESS < 255);

  // set master brightness control
  FastLED.setBrightness(BRIGHTNESS);  
}
void lights(bool On)
{
static uint16_t sPseudotime = 0;
  static uint16_t sLastMillis = 0;
  static uint16_t sHue16 = 0;
 
  uint8_t sat8 = beatsin88( 87, 220, 250);
  uint8_t brightdepth = beatsin88( 341, 96, 224);
  uint16_t brightnessthetainc16 = beatsin88( 203, (25 * 256), (40 * 256));
  uint8_t msmultiplier = beatsin88(147, 23, 60);

  uint16_t hue16 = sHue16;//gHue * 256;
  uint16_t hueinc16 = beatsin88(113, 1, 3000);
  
  uint16_t ms = millis();
  uint16_t deltams = ms - sLastMillis ;
  sLastMillis  = ms;
  sPseudotime += deltams * msmultiplier;
  sHue16 += deltams * beatsin88( 400, 5,9);
  uint16_t brightnesstheta16 = sPseudotime;
  
  for( uint16_t i = 0 ; i < NUM_LEDS; i++) {
    hue16 += hueinc16;
    uint8_t hue8 = hue16 / 256;

    brightnesstheta16  += brightnessthetainc16;
    uint16_t b16 = sin16( brightnesstheta16  ) + 32768;

    uint16_t bri16 = (uint32_t)((uint32_t)b16 * (uint32_t)b16) / 65536;
    uint8_t bri8 = (uint32_t)(((uint32_t)bri16) * brightdepth) / 65536;
    bri8 += (255 - brightdepth);
    
    CRGB newcolor = CHSV( hue8, sat8, bri8);
    
    uint16_t pixelnumber = i;
    pixelnumber = (NUM_LEDS-1) - pixelnumber;
    
    nblend( leds[pixelnumber], newcolor, 64);
  }
}  
void loop()
{
  Serial.println("Going to Sleep");
  delay(1000);
  attachInterrupt(digitalPinToInterrupt(wakeUpPin), wakeUp, RISING);
  LowPower.powerDown(SLEEP_FOREVER, ADC_OFF, BOD_OFF);
  lights(false);

  Serial.println("Woke up");
  delay(1000);
  lights(true);
}

Ah, shit. I've not been playing with the sleep mode and can't tell if Your approach is correct or not. Hopefully some other helper reads this and takes on the next level of debugging. Sorry. No guesses given consuming Your time...
To detach and attach interrupts feels strange....

is there a way that you can think of that's better?

That's not the best board to start with if you want it to use minimum power whilst sleeping.

See


For required reading on getting the most out of your batteries and all that.

a7

Nick Gammon does it, so.

a7

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