Naughty green LED on neopixel strip when triggered by PIR

Hi - My first time on the forum and with Arduino! Would love some advice/help please!
so the setup is a neopixel strip attached to an Uno. The strip has an 'eye' of LED that bounces up and down the strip when a PIR is triggered (HIGH).

I have pinched two bits of code; one that sets up the PIR to trigger stuff and a second that is my bouncing LED 'eye.

Both bits of code work fine separately, and pretty much work fine now I've put them together, other than one issue: the first LED on the strip shows up as green. I want it to behave like all the other LEDs, not show up as green.
My sketch below, and you can see what is happening here: https://youtu.be/D24Yl_rf318

Interestingly, when i run just the 'scanning eye' code on it's own i.e. not triggered by the PIR, I don't get the green LED.
I've tried to work through the code logically and see what is causing the green LED to be lit, and I can't work it out. Any ideas?

Thanks!

//Summoning skull v0.1 pir sensor ws2812 scanning 'eye'
//pir sensor ws2812 neo xmas

#include <Adafruit_NeoPixel.h>
#define N_LEDS 60
#ifdef __AVR__
  #include <avr/power.h>
#endif
#define PIN 6
// Parameter 1 = number of pixels in strip
// Parameter 2 = Arduino pin number (most are valid)
// Parameter 3 = pixel type flags, add together as needed:
Adafruit_NeoPixel strip = Adafruit_NeoPixel(N_LEDS, PIN, NEO_GRB + NEO_KHZ800);
/*
 * How to use a PIR sensor with the Arduino
http://www.electronicslovers.com/2015/08/how-to-use-pir-sensor-with-arduino.html
 * The sensor's output pin goes to HIGH if motion is present.
 * However, even if motion is present it goes to LOW from time to time, 
 * which might give the impression no motion is present. 
 * This program deals with this issue by ignoring LOW-phases shorter than a given time, 
 * assuming continuous motion is present during these phases.
*/
//the time we give the sensor to calibrate (10-60 secs according to the datasheet)
int calibrationTime = 10;         
//the time when the sensor outputs a low impulse
long unsigned int lowIn;         
//the amount of milliseconds the sensor has to be low 
//before we assume all motion has stopped
long unsigned int pause = 5000;  
boolean lockLow = true;
boolean takeLowTime;  
int pirPin = 9;    //the digital pin connected to the PIR sensor's output
int ledPin = 6; 

void setup(){
  Serial.begin(9600);
  strip.begin();
  strip.show();
  pinMode(pirPin, INPUT);
  pinMode(ledPin, OUTPUT);
  digitalWrite(pirPin, LOW);
  //give the sensor some time to calibrate
  Serial.print("calibrating sensor please wait for 10 secs ");
    for(int i = 0; i < calibrationTime; i++){
      Serial.print(".");
      delay(1000);
      }
    Serial.println(" done");
    Serial.println("SENSOR ACTIVE");
    delay(50);
  }
  int pos = 0, dir = 1; // Position, direction of "eye"
////////////////////////////
//LOOP
void loop(){
int j;
     if(digitalRead(pirPin) == HIGH){
       digitalWrite(ledPin, HIGH);   //the led visualizes the sensors output pin state
        

  // Draw 5 pixels centered on pos.  setPixelColor() will clip any
  // pixels off the ends of the strip, we don't need to watch for that.
  strip.setPixelColor(pos - 2, 0x100000); // Dark red
  strip.setPixelColor(pos - 1, 0x800000); // Medium red
  strip.setPixelColor(pos    , 0xFF3000); // Center pixel is brightest
  strip.setPixelColor(pos + 1, 0x800000); // Medium red
  strip.setPixelColor(pos + 2, 0x100000); // Dark red

  strip.show();
  delay(10);

  // Rather than being sneaky and erasing just the tail pixel,
  // it's easier to erase it all and draw a new one next time.
  for(j=-2; j<= 2; j++) strip.setPixelColor(pos+j, 0);

  // Bounce off ends of strip
  pos += dir;
  if(pos < 0) {
    pos = 1;
    dir = -dir;
  } else if(pos >= strip.numPixels()) {
    pos = strip.numPixels() - 2;
    dir = -dir;
  }
       
//        delay(100);
       if(lockLow){ 
         //makes sure we wait for a transition to LOW before any further output is made:
         lockLow = false;            
         Serial.println("---");
         Serial.print("motion detected at ");
         Serial.print(millis()/1000);
         Serial.println(" sec"); 
         delay(50);
         }         
         takeLowTime = true;
       }

     if(digitalRead(pirPin) == LOW){ 
       digitalWrite(ledPin, LOW);  //the led visualizes the sensors output pin state

       if(takeLowTime){
        strip.setPixelColor(pos - 2, 0x100000); // Dark red
        lowIn = millis();          //save the time of the transition from high to LOW
        takeLowTime = false;       //make sure this is only done at the start of a LOW phase
        }
       //if the sensor is low for more than the given pause, 
       //we assume that no more motion is going to happen
       if(!lockLow && millis() - lowIn > pause){  
           //makes sure this block of code is only executed again after 
           //a new motion sequence has been detected
           lockLow = true;                        
           Serial.print("motion ended at ");      //output
           Serial.print((millis() - pause)/1000);
           Serial.println(" secs ");
           delay(50);
           }
       }
       
  }

// Fill the dots one after the other with a color
void colorWipe(uint32_t c, uint8_t wait) {
  for(uint16_t i=0; i<strip.numPixels(); i++) {
    strip.setPixelColor(i, c);
    strip.show();
    delay(wait);
  }
}

<

are you getting off the strip with pos - 2?

i see later you assign 1 to pos

if(pos < 0) {
    pos = 1;

This comment in your code

    // Draw 5 pixels centered on pos.  setPixelColor() will clip any
    // pixels off the ends of the strip, we don't need to watch for that.
    strip.setPixelColor(pos - 2, 0x100000); // Dark red
    ...

is NOT true. The Adafruit library will ignore positions greater than the number of pixels you have, but does not do any checking for led numbers less than 0, which you have as @J-M-L pointed out

second thought:

actually as setPixelColor() takes a uint16_t as the position and you pass an int that is -1, it's received as 0xFFFF in the function and thus after the end of the strip

good point!

I don't think you should be driving your led pin HIGH. You might be creating an extra pulse or some oddity that is causing this issue

void loop() {
  int j;
  if (digitalRead(pirPin) == HIGH) {
    digitalWrite(ledPin, HIGH);   //the led visualizes the sensors output pin state
    ...

I would try removing or commenting out that line

that's far fetched

what's the purpose of setting the pos - 2 pixel to Dark red and not refreshing the strip?

    if (takeLowTime) {
      strip.setPixelColor(pos - 2, 0x100000); // Dark red
      lowIn = millis();          //save the time of the transition from high to LOW
      takeLowTime = false;       //make sure this is only done at the start of a LOW phase
    }

Hi everyone, thanks for taking the time to look at this. I'll try taking that line out @blh64. As for the purpose of setting the pos-2 pixel to dark Red and not refreshing, @J-M-L I have no idea! It must be something to do with th scanning eye part of the code though, as the green LED does not appear when running each snippet separately. And why green?

Thanks!

You mean it’s not your code?

No. I 'borrowed' two core bits of code and put them together. They work fine separately and mostly fine together other than this green LED artifact. I'm right at the beginning of learning coding so a lot of these calls and instructions are new to me, hence why I'm struggling to work out what is doing what! I really appreciate the help!

How are you powering and grounding the strip?

That pixel color you set without showing it is useless. Remove it

Strip is powered and grounded from a bench supply.

That line would never work with a programmable LED strip. Was the PIR code by any chance meant for a discrete LED?

Also, doing both of these is silly:

#define PIN 6
int ledPin = 6; 

You only have one Pin #6, why give it two names?

Copy / Paste programming is almost never a good idea. It's better to completely understand how each program works separately and then write a new program that combines the functions, not combines the code lines verbatim.

did you join the GND ?

did you try removing the strip.setPixelColor(pos - 2, 0x100000); // Dark red line?

I totally agree! This is part of the learning process for me; seeing what approaches actually work (as there seem to be a million ways of doing something) and when something seems to work I will rewrite the code. It's a risky way of learning as it means I can pick up bad habits I know, but it's getting me used to the syntax and process!

B O O M! That worked - green LED has gone!
Now I'll go through and sort my variables and tidy up the code.

Thanks so much everyone!

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