Self-sustaining light box with pixelleds, code problems

Hey good day
I wanted to ask briefly because I am building a light box, and it works as followed:

A small solar board charges a small 2700mAh battery and this keeps an Arduino Nano alive. This is woken up from sleep mode by a photoresistor. After that, the PIR registers a movement and there is a pulsating LED. Now I have built a working code for simple LED strips via PWM. Now I would like to use Pixel LED, but I can't get this code to work ... Maybe you can help me.

This is the working PWM code (only the Serial print is doing his job a bit ugly, so it rows up AwAwAw and not fully spelling Awake if someone know how to solve this)

#include <Sleep_n0m1.h>

Sleep sleep;

#define intPin 2
const unsigned int ledPin = 10;
const unsigned int ledPin2 = 11;
boolean active = false; //Zwischenvariable
int pin = 3; // Datenpin festlegen
int movement = 0;

void setup()//Hier beginnt das Setup.
{
Serial.begin(9600); // Serialmonitor
pinMode (ledPin, OUTPUT); //LED PIN
pinMode(pin, INPUT); // Data PIR
  CLKPR = 0x80; // (1000 0000) enable change in clock frequency
  CLKPR = 0x03; // (0000 0001) use clock division factor 2 to reduce the frequency from 16 MHz to 8 MHz

}

void loop()
{

  
{
movement = digitalRead(pin); // Sensor auslesen

if(movement == HIGH && active == false){
active = true;
Serial.println("Bewegung erkannt");
}
// keine Bewegung nachdem eine Bewegung erkannt wurde
if(movement == LOW && active == true){
active = false;
Serial.println("Keine Bewegung");
}
if (movement == HIGH ) //Wenn der PIR Bewegung erkennt
{
for (int fadeValue = 25 ; fadeValue <= 220; fadeValue += 5) {

    // sets the value (range from 0 to 255):

    analogWrite(ledPin, fadeValue);
      analogWrite(ledPin2, fadeValue);

    // wait for 30 milliseconds to see the dimming effect

    delay(15);
      }

  // fade out from max to min in increments of 5 points:
  for (int fadeValue = 220 ; fadeValue >= 25; fadeValue -= 5) {

    // sets the value (range from 0 to 255):
    
    analogWrite(ledPin2, fadeValue);
    analogWrite(ledPin, fadeValue);
   

    // wait for 30 milliseconds to see the dimming effect

    delay(15);

  }
}  
else //andernfalls…
{
analogWrite(ledPin2, 0);
analogWrite(ledPin, 0);
}
delay (50);//Eine kurze Pause, in der die LED an oder aus ist
}
  delay(100); ////delays are just for serial print, without serial they can be removed
  Serial.println("awk");

  Serial.print("Sleeping");

  delay(100); //delay to allow serial to fully print before sleep

  sleep.pwrDownMode(); //set sleep mode

  //Sleep till interrupt pin equals a particular state.
  //In this case "low" is state 0.
  sleep.sleepPinInterrupt(intPin,LOW); //(interrupt Pin Number, interrupt State)
  }

  

That's the try-out for the PixelLeds and still not working (it's up loadable but hanging its self and won't work with the sleep mode);

#include <Sleep_n0m1.h>
#include <Adafruit_NeoPixel.h>


Sleep sleep;

#define intPin 2
#define PIN 6
Adafruit_NeoPixel strip = Adafruit_NeoPixel(19, PIN, NEO_GRB + NEO_KHZ800);
boolean active = false; //Zwischenvariable
int pin = 3; // Datenpin festlegen
int movement = 0;

void setup()//Hier beginnt das Setup.
{
Serial.begin(9600); // Serialmonitor
  strip.begin();
  strip.setBrightness(85);  // Lower brightness and save eyeballs!
  strip.show(); // Initialize all pixels to 'off'
pinMode(pin, INPUT); // Data PIR
  CLKPR = 0x80; // (1000 0000) enable change in clock frequency
  CLKPR = 0x03; // (0000 0001) use clock division factor 2 to reduce the frequency from 16 MHz to 8 MHz

}

void loop()
{

  
{
movement = digitalRead(pin); // Sensor auslesen

if(movement == HIGH && active == false){
active = true;
Serial.println("Bewegung erkannt");
}
// keine Bewegung nachdem eine Bewegung erkannt wurde
if(movement == LOW && active == true){
active = false;
Serial.println("Keine Bewegung");
}
if (movement == HIGH ) //Wenn der PIR Bewegung erkennt
{

int TOTAL_LEDS = 60;
float MaximumBrightness = 255;
float SpeedFactor = 0.008; // I don't actually know what would look good
float StepDelay = 5; // ms for a step delay on the lights

// Make the lights breathe
for (int i = 0; i < 65535; i++) {
// Intensity will go from 10 - MaximumBrightness in a "breathing" manner
float intensity = MaximumBrightness /2.0 * (1.0 + sin(SpeedFactor * i));
strip.setBrightness(intensity);
// Now set every LED to that color
for (int ledNumber=0; ledNumber<TOTAL_LEDS; ledNumber++) {
strip.setPixelColor(ledNumber, 255, 0, 200);
}

strip.show();
//Wait a bit before continuing to breathe
delay(StepDelay);

}
}  
else //andernfalls…
{
 strip.clear();
}
delay (50);//Eine kurze Pause, in der die LED an oder aus ist
}
  delay(100); ////delays are just for serial print, without serial they can be removed
  Serial.println("awk");

  Serial.print("Sleeping");

  delay(100); //delay to allow serial to fully print before sleep

  sleep.pwrDownMode(); //set sleep mode

  //Sleep till interrupt pin equals a particular state.
  //In this case "low" is state 0.
  sleep.sleepPinInterrupt(intPin,LOW); //(interrupt Pin Number, interrupt State)
  }

  

Looking forward for help, and here are some pictures of the PWM version of it:

1 Like

You got the led strip to work by itself?

BTW, great first post.

Here you are declaring your led strip has 19 leds...

Here you say you have 60.

That line will be true for all eternity. Since i is an int it will go from 0..32767 and then -32768..0.
If you make i an unsigned int then it goes from 0..65535, so will be false on the last iteration.

If you hit Ctrl-T in the IDE, it will tidy up your code a bit and you will see you have an extra pair of curly brackets inside loop()... [doesn't hurt anything, but not needed]

Yes, they run directly from the PWM outputs of the Arduinos, with max. 40mA each.

you might save some ram space by using ints.

Did you address the tip from post#3?

Thanks a lot for the fast response

First I will check the number of LED and then check the fade (interestingly it works isolated, so only the LED without sleep mode). And then i will try to make the i as a unsigned int and also hit Ctrl-T and Update the post in the coming days ;)!

So you mean to use unsigned int?

Yes, I will adjust it and update the post! :wink:

Please DO NOT update the post. Post a reply with the new code. Re-writing history make a thread difficult to read/follow

1 Like

Thank you, I will do so :slight_smile:

So, I fixed the code, but it only works if I leave the clock frequency normal, otherwise the control signal for the LEDs seems to hang up. Now there would be the option probably in the Adadfruit library to adjust the output frequency of the data signal or to reduce the clock frequency only in sleep mode (For the basic understanding, I reduced the clock frequency to save energy and would like to leave it at 2mA > 10 mA...). Since this is now too complicated for me and I finally get along well without Pixelleds (these are only there to not exceed the maximum of the PWM outputs) I will probably the PWM signal via a transistor, maybe someone can recommend me a transistor or a circuit to do that, or I am on the wrong way :slight_smile:?

Enclosed still the correction:

#include <Sleep_n0m1.h>
#include <Adafruit_NeoPixel.h>


Sleep sleep;

#define intPin 2
#define PIN 6
Adafruit_NeoPixel strip = Adafruit_NeoPixel(19, PIN, NEO_RGB + NEO_KHZ800);
boolean active = false; //Zwischenvariable
int pin = 3; // Datenpin festlegen
int movement = 0;

void setup()//Hier beginnt das Setup.
{
  Serial.begin(9600); // Serialmonitor
  strip.begin();
  strip.setBrightness(85);  // Lower brightness and save eyeballs!
  strip.show(); // Initialize all pixels to 'off'
  pinMode(pin, INPUT); // Data PIR
  CLKPR = 0x80; // (1000 0000) enable change in clock frequency
  CLKPR = 0x02; // (0000 0001) use clock division factor 2 to reduce the frequency from 16 MHz to 8 MHz

}

void loop()
{


  {
    movement = digitalRead(pin); // Sensor auslesen

    if (movement == HIGH && active == false) {
      active = true;
      Serial.println("Bewegung erkannt");
    }
    // keine Bewegung nachdem eine Bewegung erkannt wurde
    if (movement == LOW && active == true) {
      active = false;
      Serial.println("Keine Bewegung");
    }
    if (movement == HIGH ) //Wenn der PIR Bewegung erkennt
    {

      int TOTAL_LEDS = 19;
      float MaximumBrightness = 255;
      float SpeedFactor = 0.008; // I don't actually know what would look good
      float StepDelay = 5; // ms for a step delay on the lights

      // Make the lights breathe
      for (unsigned int i = 0; i < 65535; i++) {
        // Intensity will go from 10 - MaximumBrightness in a "breathing" manner
        float intensity = MaximumBrightness / 2.0 * (1.0 + sin(SpeedFactor * i));
        strip.setBrightness(intensity);
        // Now set every LED to that color
        for (int ledNumber = 0; ledNumber < TOTAL_LEDS; ledNumber++) {
          strip.setPixelColor(ledNumber, 255, 0, 200);
        }

        strip.show();
        //Wait a bit before continuing to breathe
        delay(StepDelay);

      }
    }
    else //andernfalls…
    {
      strip.clear();
    }
    delay (50);//Eine kurze Pause, in der die LED an oder aus ist
  }
  delay(100); ////delays are just for serial print, without serial they can be removed
  Serial.println("awk");

  Serial.print("Sleeping");

  delay(100); //delay to allow serial to fully print before sleep

  sleep.pwrDownMode(); //set sleep mode

  //Sleep till interrupt pin equals a particular state.
  //In this case "low" is state 0.
  sleep.sleepPinInterrupt(intPin, LOW); //(interrupt Pin Number, interrupt State)
}

Does reducing the clock speed really help? That just makes everything take twice as long, keeping the processor awake longer. Personally I would not worry about the processor power usage, the LEDs are going to use the vast majority of the power, and using 1/2 clock speed just keeps those on twice as long.

If you really want to use Adafruit NeoPixel with an 8MHz clock, use MCUdude's MiniCore to burn the bootloader with the internal clock set to 8MHz, then the timing will work correctly, otherwise you can modify the library to force the timing to 8MHz.

Replace the delay(100) with Serial.flush(), flush() is a blocking function that will return when all the serial data has been sent.

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