finding the current lit up pixel

Hi all, I'm currently working with a WS2812B LED strip and the NeoPixel Arduino library and hoping to get some help with coding, as I'm pretty new to Arduino and coding in general.

I've got the LED strip and an ultrasonic (ping) sensor connected up to the Arduino Uno right now. I've got 10 pixels lit up at a time, and I want these ten pixels to move from their current location gradually along the strip to a different location depending on the output of the sensor.

So an example in layman's terms would be:

If the sensor output is between 0 and 5 cm, take the currently lit ten pixels and move them along the strip (dimming the first pixel off and the last pixel on) until the first pixel (of the ten) reaches pixel 30.

Not sure if that's clear enough, but let me know if you have questions about that. What I'm mostly trying to figure out is a.) how do I ask the Arduino to find the currently lit pixels? and b.) how can I from these currently lit 10 pixels dim the first pixel off and the last pixel on, as it moves along the strip to the next location? I'm figuring that I will have to constantly ask the Arduino which pixels are lit up until I get to the desired location (in the above example, pixel 30), will this cause too much lag?

FYI here’s the code I’m using right now. It’s not even close to what I want…still need to put some if statements in there instead of just plugging the sensor output directly into the pixel on the LED.

#include <Adafruit_NeoPixel.h>
#ifdef __AVR__
 #include <avr/power.h>
#endif
#include <NewPing.h>
#define filterSamples 13
#define TRIGGER_PIN  12  // Arduino pin tied to trigger pin on the ultrasonic sensor.
#define ECHO_PIN     11  // Arduino pin tied to echo pin on the ultrasonic sensor.
#define MAX_DISTANCE 400 // Maximum distance we want to ping for (in centimeters). Maximum sensor distance is rated at 400-500cm.
#define PIN 6
Adafruit_NeoPixel strip = Adafruit_NeoPixel(60, PIN, NEO_GRB + NEO_KHZ800);
NewPing sonar(TRIGGER_PIN, ECHO_PIN, MAX_DISTANCE); // NewPing setup of pins and maximum distance.

int PingArray [filterSamples];
int rawPing, smoothDist, newsmooth;

void setup() {
 Serial.begin(115200); // Open serial monitor at 115200 baud to see ping results.
   #if defined (__AVR_ATtiny85__)
   if (F_CPU == 16000000) clock_prescale_set(clock_div_1);
 #endif
 strip.begin();
 strip.show(); // Initialize all pixels to 'off'
}

void loop() {
 //delay(100);                     // Wait 50ms between pings (about 20 pings/sec). 29ms should be the shortest delay between pings.
 rawPing = sonar.ping_cm();
 smoothDist = digitalSmooth(rawPing, PingArray);
 
 Serial.print("Ping: ");
 Serial.print(rawPing); // Send ping, get distance in cm and print result (0 = outside set distance range)
 Serial.print("  ");
 Serial.println(smoothDist);
 int x = smoothDist;
 int y = smoothDist+10;
 if(newsmooth!=smoothDist){
 light(x,y);
 }
 newsmooth = smoothDist;
 
}

int digitalSmooth(int rawIn, int *sensSmoothArray){     // "int *sensSmoothArray" passes an array to the function - the asterisk indicates the array name is a pointer
 int j, k, temp, top, bottom;
 long total;
 static int i;
// static int raw[filterSamples];
 static int sorted[filterSamples];
 boolean done;

 i = (i + 1) % filterSamples;    // increment counter and roll over if necc. -  % (modulo operator) rolls over variable
 sensSmoothArray[i] = rawIn;                 // input new data into the oldest slot

 // Serial.print("raw = ");

 for (j=0; j<filterSamples; j++){     // transfer data array into anther array for sorting and averaging
   sorted[j] = sensSmoothArray[j];
 }

 done = 0;                // flag to know when we're done sorting              
 while(done != 1){        // simple swap sort, sorts numbers from lowest to highest
   done = 1;
   for (j = 0; j < (filterSamples - 1); j++){
     if (sorted[j] > sorted[j + 1]){     // numbers are out of order - swap
       temp = sorted[j + 1];
       sorted [j+1] =  sorted[j] ;
       sorted [j] = temp;
       done = 0;
     }
   }
 }

/*
 for (j = 0; j < (filterSamples); j++){    // print the array to debug
   Serial.print(sorted[j]); 
   Serial.print("   "); 
 }
 Serial.println();
*/

 // throw out top and bottom 15% of samples - limit to throw out at least one from top and bottom
 bottom = max(((filterSamples * 15)  / 100), 1); 
 top = min((((filterSamples * 85) / 100) + 1  ), (filterSamples - 1));   // the + 1 is to make up for asymmetry caused by integer rounding
 k = 0;
 total = 0;
 for ( j = bottom; j< top; j++){
   total += sorted[j];  // total remaining indices
   k++; 
   // Serial.print(sorted[j]); 
   // Serial.print("   "); 
 }

//  Serial.println();
//  Serial.print("average = ");
//  Serial.println(total/k);
 return total / k;    // divide by number of samples
}

void light(uint16_t begin, uint16_t end){
 for(uint16_t z = 0; z < strip.numPixels(); z++){
   if(z <begin){
     strip.setPixelColor(z, 0, 0, 0);
     strip.show();
   }
   else if (z > end){
     
     strip.setPixelColor(z, 0, 0, 0);
     strip.show(); 
   }
   else{
     //for(uint16_t k=0; k<51; k++){
     //strip.setPixelColor(z, k*10, k*10, k*10);
     //strip.show();
     strip.setPixelColor(z, 255, 255, 255);
     strip.show();
     }
   }
 }
   //for(uint16_t z = 0; z < strip.numPixels(); z++){
     //strip.setPixelColor(z, 0, 0, 0);
     //strip.show();
   //}

Please edit your post above and put in code tags so it looks likethis

Code tags added. Thanks!

You can not detect when a pixel is lit. The AdaFruit library uses an array that transfers the data into the strip. You can if you want look at the values in that array and shift them along.

However it strikes me that you don't need to do that at all. 1) write a function to wipe the string, that is set all the values in the buffer to zero. 2) then simply put your slug of 10 LEDs into that buffer, starting at a number given by your sensor. You can change the values of each LED by simply having an array of your slug and copying it into the neopixel array at the appropriate point.

Okay! Thank you for the reply. It's good to know at least that the library can't detect the lit up pixels.

nvolp: It's good to know at least that the library can't detect the lit up pixels.

Well, the point is that there is absolutely no need for it to "detect" the lit up pixels.

The library is what tells the pixels what to display. The library knows what pixels are lit, because it keeps an image of them in RAM - that image is read out to the pixels (in its entirety) each time it is necessary and you instruct it to update them (but only then, not before). The library might provide a means to read that RAM image for all I know.

But in general, to move a pattern along, for each step, you can firstly "turn off" the pattern that you last wrote, then "turn on" the new pattern, then tell the library to update the pixels. Because you have not actually changed them until that last step, there is no flicker resulting from this, however you may find it more efficient to only turn off the pixels that were part of the old pattern and not part of the new, and only turn on the pixels that were part of the new pattern and not part of the old, in that RAM image.