NeoPixel help on Flora with LSM303

Hello! I’m working on a costume project using a [Flora] and an [ACCELEROMETER/COMPASS SENSOR - LSM303] which I think might have been a bad idea since It seems to be a lot harder to code then I expected.
I have it working so far that when the thing is upright it’ll do an animation on the neopixels, and goes dim when upside down.

the things I’m having trouble with is:

  • Add a separate line of neopixles that the LSM303 won’t effect it and just slowly fade in and out.
  • change the upright animation to a chase instead of a fade

Another thing I wanted to add but is not a big deal if I cant is a “flashlight mode” where I can activate it with a command to the LSM303 (tapping?) and change the main lights to a bright white until the command is inputted to deactivate it. but it seems like trying to program this in might be a bit difficult.

If anyone can give me some help on this it would be greatly appreciated! If I can at least get the separate lights working It’ll be good enough to use.

#include <Wire.h>
#include <Adafruit_Sensor.h>
#include <Adafruit_LSM303_U.h>
#include <Adafruit_NeoPixel.h>
#ifdef __AVR__
  #include <avr/power.h>
#endif

#define PIN 10

unsigned long interval=500;  // the time we need to wait
unsigned long previousMillis=0;

uint32_t currentColor;// current Color in case we need it
uint16_t currentPixel = 0;// what pixel are we operating on
Adafruit_NeoPixel strip = Adafruit_NeoPixel(7, PIN, NEO_GRB + NEO_KHZ800);


/* Assign a unique ID to this sensor at the same time */
Adafruit_LSM303_Accel_Unified accel = Adafruit_LSM303_Accel_Unified(54321);
Adafruit_LSM303_Mag_Unified mag = Adafruit_LSM303_Mag_Unified(12345);

int led = 7;
int led1 = 1;   
int led2 = 0;
int led3 = 12;
int led4 = 6;


void setup(void)
{
   // Initialize the sensors
   accel.begin();
   mag.begin();

   pinMode(led, OUTPUT);
   pinMode(led1, OUTPUT);
   pinMode(led2, OUTPUT);
   pinMode(led3, OUTPUT);
   pinMode(led4, OUTPUT);

  currentColor = strip.Color(24, 100, 100); // Science Glow
  currentPixel = 0;
  strip.begin();
  strip.show(); // Initialize all pixels to 'off'

   }

// ---------------------------------------
// Linear interpolation of y value given min/max x, min/max y, and x position.
float lerp(float x, float x0, float x1, float y0, float y1)
{
  // Clamp x within x0 and x1 bounds.
  x = x > x1 ? x1 : x;
  x = x < x0 ? x0 : x;
  // Calculate linear interpolation of y value.
  return y0 + (y1-y0)*((x-x0)/(x1-x0));
}
 
// Set all pixels to the specified color.
void fill_pixels(Adafruit_NeoPixel& pixels, uint32_t color)
{
  for (int i=0; i < pixels.numPixels(); ++i) {
    pixels.setPixelColor(i, color);
  }
  strip.show();

}



// Get the color of a pixel within a smooth gradient of two colors.
uint32_t color_gradient(uint8_t start_r, // Starting R,G,B color
                        uint8_t start_g,
                        uint8_t start_b, 
                        uint8_t end_r,   // Ending R,G,B color
                        uint8_t end_g,
                        uint8_t end_b,
                        float pos)       // Position along gradient, should be a value 0 to 1.0
{
  // Interpolate R,G,B values and return them as a color.  
  uint8_t red   = (uint8_t) lerp(pos, 0.0, 1.0, start_r, end_r);
  uint8_t green = (uint8_t) lerp(pos, 0.0, 1.0, start_g, end_g);
  uint8_t blue  = (uint8_t) lerp(pos, 0.0, 1.0, start_b, end_b);
  return Adafruit_NeoPixel::Color(red, green, blue);
}
 
void animate_gradient_fill(Adafruit_NeoPixel& pixels, // NeoPixel strip/loop/etc.
                           uint8_t start_r,           // Starting R,G,B color
                           uint8_t start_g,
                           uint8_t start_b, 
                           uint8_t end_r,             // Ending R,G,B color
                           uint8_t end_g,
                           uint8_t end_b,
                           int duration_ms)           // Total duration of animation, in milliseconds
{
  unsigned long start = millis();
  // Display start color.
  fill_pixels(pixels, Adafruit_NeoPixel::Color(start_r, start_g, start_b));
  // Main animation loop.
  unsigned long delta = millis() - start;
  while (delta < duration_ms) {
    // Calculate how far along we are in the duration as a position 0...1.0
    float pos = (float)delta / (float)duration_ms;
    // Get the gradient color and fill all the pixels with it.
    uint32_t color = color_gradient(start_r, start_g, start_b, end_r, end_g, end_b, pos);
    fill_pixels(pixels, color);
    // Update delta and repeat.
    delta = millis() - start;
  }
  // Display end color.
  fill_pixels(pixels, Adafruit_NeoPixel::Color(end_r, end_g, end_b));
}
//---------------------------------------
void loop(void)
{

  /* Get a new sensor event */
  sensors_event_t event;
  accel.getEvent(&event);
 
   // Calculate the angle of the vector y,x from magnetic North
   float heading = (event.magnetic.z);
   


if (heading > 6){
    Serial.println("Right side up");
    // Normal LED's on
      digitalWrite(led, HIGH);
      digitalWrite(led1, HIGH);
      digitalWrite(led2, HIGH);
      digitalWrite(led3, HIGH);
      digitalWrite(led4, HIGH);
      
// Nice fade from dim blue to full blue for 1/2 of a second:
  animate_gradient_fill(strip,         
                      3, 12, 12,
                      24, 100, 100,
                      500);
  // Then fade from full blue to dim blue for 1/2 a second.
  animate_gradient_fill(strip,         
                      24, 100, 100,
                      6, 25, 25,
                      500);
  //delay(1000); Use this delay if using multiple color fades

      
}
else{
    Serial.println("Upside down");
      digitalWrite(led, LOW);
      digitalWrite(led1, HIGH);
      digitalWrite(led2, HIGH);
      digitalWrite(led3, HIGH);
      digitalWrite(led4, HIGH);


 }
}

You can either create another NoePixel strip using a different pin, if you have one, or you can make your current strip twice as long and then just program the first half based on the LSM303 and the second half can dim/glow however you want.

I tired to set it up with a different pin and using the colorWipe code, But I was never able to get it to work at all.

And only you know what you tried since you provided no code.

It turns out I was trying to program the Flora wrong, so all my previous attempts didn’t even get loaded onto it.

I was able to get the extra lights to work, but the first LED on each of the strips on PIN_2 and PIN_3 blinks green after each loop.
I want to have them both fading on there own separate loop from the main lights, but I haven’t been able to figure that part out.

#include <Wire.h>
#include <Adafruit_Sensor.h>
#include <Adafruit_LSM303_U.h>
#include <Adafruit_NeoPixel.h>
#ifdef __AVR__
  #include <avr/power.h>
#endif

#define PIN 10
#define PIN_2 12
#define PIN_3 0

unsigned long interval=500;  // the time we need to wait
unsigned long previousMillis=0;


uint32_t currentColor;// current Color in case we need it
uint16_t currentPixel = 1;// what pixel are we operating on
Adafruit_NeoPixel strip = Adafruit_NeoPixel(7, PIN, NEO_GRB + NEO_KHZ800);
Adafruit_NeoPixel strip_b = Adafruit_NeoPixel(2, PIN_2, NEO_GRB + NEO_KHZ800);
Adafruit_NeoPixel strip_c = Adafruit_NeoPixel(2, PIN_3, NEO_GRB + NEO_KHZ800);

/* Assign a unique ID to this sensor at the same time */
Adafruit_LSM303_Accel_Unified accel = Adafruit_LSM303_Accel_Unified(54321);
Adafruit_LSM303_Mag_Unified mag = Adafruit_LSM303_Mag_Unified(12345);

int led = 7;
int led1 = 1;   
int led2 = 0;
int led3 = 12;
int led4 = 6;


void setup(void)
{
   // Initialize the sensors
   accel.begin();
   mag.begin();

   pinMode(led, OUTPUT);
   pinMode(led1, OUTPUT);
   pinMode(led2, OUTPUT);
   pinMode(led3, OUTPUT);
   pinMode(led4, OUTPUT);

  currentColor = strip.Color(24, 100, 100); // Science Glow
  currentPixel = 0;
  strip.begin();
  strip.show(); // Initialize all pixels to 'off'

  strip_b.begin();
  strip_b.show(); // Initialize all pixels to 'off'  
  strip_c.begin();
  strip_c.show(); // Initialize all pixels to 'off'  
   }

// ---------------------------------------
// Linear interpolation of y value given min/max x, min/max y, and x position.
float lerp(float x, float x0, float x1, float y0, float y1)
{
  // Clamp x within x0 and x1 bounds.
  x = x > x1 ? x1 : x;
  x = x < x0 ? x0 : x;
  // Calculate linear interpolation of y value.
  return y0 + (y1-y0)*((x-x0)/(x1-x0));
}
 
// Set all pixels to the specified color.
void fill_pixels(Adafruit_NeoPixel& pixels, uint32_t color)
{
  for (int i=0; i < pixels.numPixels(); ++i) {
    pixels.setPixelColor(i, color);
  }
  strip.show();
}



// Get the color of a pixel within a smooth gradient of two colors.
uint32_t color_gradient(uint8_t start_r, // Starting R,G,B color
                        uint8_t start_g,
                        uint8_t start_b, 
                        uint8_t end_r,   // Ending R,G,B color
                        uint8_t end_g,
                        uint8_t end_b,
                        float pos)       // Position along gradient, should be a value 0 to 1.0
{
  // Interpolate R,G,B values and return them as a color.  
  uint8_t red   = (uint8_t) lerp(pos, 0.0, 1.0, start_r, end_r);
  uint8_t green = (uint8_t) lerp(pos, 0.0, 1.0, start_g, end_g);
  uint8_t blue  = (uint8_t) lerp(pos, 0.0, 1.0, start_b, end_b);
  return Adafruit_NeoPixel::Color(red, green, blue);
}
 
void animate_gradient_fill(Adafruit_NeoPixel& pixels, // NeoPixel strip/loop/etc.
                           uint8_t start_r,           // Starting R,G,B color
                           uint8_t start_g,
                           uint8_t start_b, 
                           uint8_t end_r,             // Ending R,G,B color
                           uint8_t end_g,
                           uint8_t end_b,
                           int duration_ms)           // Total duration of animation, in milliseconds
{
  unsigned long start = millis();
  // Display start color.
  fill_pixels(pixels, Adafruit_NeoPixel::Color(start_r, start_g, start_b));
  // Main animation loop.
  unsigned long delta = millis() - start;
  while (delta < duration_ms) {
    // Calculate how far along we are in the duration as a position 0...1.0
    float pos = (float)delta / (float)duration_ms;
    // Get the gradient color and fill all the pixels with it.
    uint32_t color = color_gradient(start_r, start_g, start_b, end_r, end_g, end_b, pos);
    fill_pixels(pixels, color);
    // Update delta and repeat.
    delta = millis() - start;
  }
  // Display end color.
  fill_pixels(pixels, Adafruit_NeoPixel::Color(end_r, end_g, end_b));
}
//---------------------------------------
void loop(void)
{

  /* Get a new sensor event */
  sensors_event_t event;
  accel.getEvent(&event);
 
   // Calculate the angle of the vector y,x from magnetic North
   float heading = (event.magnetic.z);


if (heading > 6){
    Serial.println("Right side up");
    // Normal LED's on
      digitalWrite(led, HIGH);
      digitalWrite(led1, HIGH);
      digitalWrite(led2, HIGH);
      digitalWrite(led3, HIGH);
      digitalWrite(led4, HIGH);
  strip.setBrightness(255);                // Set LED brightness 0-255
  theaterChase(strip.Color(24, 100, 100), 10); // Science Glow blink
  
      }

else{
    Serial.println("Upside down");
      digitalWrite(led, LOW);
      digitalWrite(led1, HIGH);
      digitalWrite(led2, HIGH);
      digitalWrite(led3, HIGH);
      digitalWrite(led4, HIGH);

  strip.setBrightness(30);                // Set LED brightness 0-255
     colorWipe(strip.Color(24, 100, 100), 1); // Science Glow
     
     colorWipe2(strip_b.Color(24, 100, 100), 10); // Science Glow
     colorWipe3(strip_c.Color(24, 100, 100), 10); // Science Glow         
 }

}

// 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(90);  // starting speed
  }

}

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

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

//Theatre-style crawling lights.
void theaterChase(uint32_t c, uint8_t wait) {
  for (int j=0; j<10; j++) {  //do 10 cycles of chasing
    for (int q=0; q < 3; q++) {
      for (uint16_t i=0; i < strip.numPixels(); i=i+3) {
        strip.setPixelColor(i+q, c);    //turn every third pixel on
      }
      strip.show();

      delay(50); //chaseing speed

      for (uint16_t i=0; i < strip.numPixels(); i=i+3) {
        strip.setPixelColor(i+q, 0);        //turn every third pixel off
      }
    }
  }
}

You have led2 and led3 defined as the pins used for strip_b and strip_c. This will not work. The pins for the strips are the data pins that are used to clock the data out to all the pixels in the array. It can not also be just an LED that is HIGH/LOW. Which is it?

You also can simplify the code by passing in which strip you are working on to ColorWipe() [note: you dont use the wait parameter so that could be removed]

Finally, you code has many delay()s in it as well as lots of for() loops inside your animation routines. If you want to be able to do these things “at the same time” then you can’t structure it this way. You have to do small steps and then return rather than doing the entire animation before returning to loop().

#include <Wire.h>
#include <Adafruit_Sensor.h>
#include <Adafruit_LSM303_U.h>
#include <Adafruit_NeoPixel.h>
#ifdef __AVR__
#include <avr/power.h>
#endif

const byte PIN = 10;
const byte PIN_2 = 12;
const byte PIN_3 = 0;

const unsigned long interval = 500; // the time we need to wait
unsigned long previousMillis = 0;

uint32_t currentColor;// current Color in case we need it
uint16_t currentPixel = 1;// what pixel are we operating on
Adafruit_NeoPixel strip = Adafruit_NeoPixel(7, PIN, NEO_GRB + NEO_KHZ800);
Adafruit_NeoPixel strip_b = Adafruit_NeoPixel(2, PIN_2, NEO_GRB + NEO_KHZ800);
Adafruit_NeoPixel strip_c = Adafruit_NeoPixel(2, PIN_3, NEO_GRB + NEO_KHZ800);

/* Assign a unique ID to this sensor at the same time */
Adafruit_LSM303_Accel_Unified accel = Adafruit_LSM303_Accel_Unified(54321);
Adafruit_LSM303_Mag_Unified mag = Adafruit_LSM303_Mag_Unified(12345);

const byte led = 7;
const byte led1 = 1;
const byte led2 = 0;
const byte led3 = 12;
const byte led4 = 6;

void setup(void)
{
  // Initialize the sensors
  accel.begin();
  mag.begin();

  pinMode(led, OUTPUT);
  pinMode(led1, OUTPUT);
  pinMode(led2, OUTPUT);
  pinMode(led3, OUTPUT);
  pinMode(led4, OUTPUT);

  currentColor = strip.Color(24, 100, 100); // Science Glow
  currentPixel = 0;
  strip.begin();
  strip.show(); // Initialize all pixels to 'off'

  strip_b.begin();
  strip_b.show(); // Initialize all pixels to 'off'
  strip_c.begin();
  strip_c.show(); // Initialize all pixels to 'off'
}

// ---------------------------------------
// Linear interpolation of y value given min/max x, min/max y, and x position.
float lerp(float x, float x0, float x1, float y0, float y1)
{
  // Clamp x within x0 and x1 bounds.
  x = x > x1 ? x1 : x;
  x = x < x0 ? x0 : x;
  // Calculate linear interpolation of y value.
  return y0 + (y1 - y0) * ((x - x0) / (x1 - x0));
}

// Set all pixels to the specified color.
void fill_pixels(Adafruit_NeoPixel& pixels, uint32_t color)
{
  for (int i = 0; i < pixels.numPixels(); ++i) {
    pixels.setPixelColor(i, color);
  }
  //strip.show();
  pixels.show();
}


// Get the color of a pixel within a smooth gradient of two colors.
uint32_t color_gradient(uint8_t start_r, // Starting R,G,B color
                        uint8_t start_g,
                        uint8_t start_b,
                        uint8_t end_r,   // Ending R,G,B color
                        uint8_t end_g,
                        uint8_t end_b,
                        float pos)       // Position along gradient, should be a value 0 to 1.0
{
  // Interpolate R,G,B values and return them as a color.
  uint8_t red   = (uint8_t) lerp(pos, 0.0, 1.0, start_r, end_r);
  uint8_t green = (uint8_t) lerp(pos, 0.0, 1.0, start_g, end_g);
  uint8_t blue  = (uint8_t) lerp(pos, 0.0, 1.0, start_b, end_b);
  return Adafruit_NeoPixel::Color(red, green, blue);
}

void animate_gradient_fill(Adafruit_NeoPixel& pixels, // NeoPixel strip/loop/etc.
                           uint8_t start_r,           // Starting R,G,B color
                           uint8_t start_g,
                           uint8_t start_b,
                           uint8_t end_r,             // Ending R,G,B color
                           uint8_t end_g,
                           uint8_t end_b,
                           int duration_ms)           // Total duration of animation, in milliseconds
{
  unsigned long start = millis();
  // Display start color.
  fill_pixels(pixels, Adafruit_NeoPixel::Color(start_r, start_g, start_b));
  // Main animation loop.
  unsigned long delta = millis() - start;
  while (delta < duration_ms) {
    // Calculate how far along we are in the duration as a position 0...1.0
    float pos = (float)delta / (float)duration_ms;
    // Get the gradient color and fill all the pixels with it.
    uint32_t color = color_gradient(start_r, start_g, start_b, end_r, end_g, end_b, pos);
    fill_pixels(pixels, color);
    // Update delta and repeat.
    delta = millis() - start;
  }
  // Display end color.
  fill_pixels(pixels, Adafruit_NeoPixel::Color(end_r, end_g, end_b));
}
//---------------------------------------
void loop(void)
{
  /* Get a new sensor event */
  sensors_event_t event;
  accel.getEvent(&event);

  // Calculate the angle of the vector y,x from magnetic North
  float heading = (event.magnetic.z);

  if (heading > 6) {
    Serial.println("Right side up");
    // Normal LED's on
    digitalWrite(led, HIGH);
    digitalWrite(led1, HIGH);
    digitalWrite(led2, HIGH);
    digitalWrite(led3, HIGH);
    digitalWrite(led4, HIGH);
    strip.setBrightness(255);                // Set LED brightness 0-255
    theaterChase(strip.Color(24, 100, 100), 10); // Science Glow blink
  }
  else {
    Serial.println("Upside down");
    digitalWrite(led, LOW);
    digitalWrite(led1, HIGH);
    digitalWrite(led2, HIGH);
    digitalWrite(led3, HIGH);
    digitalWrite(led4, HIGH);
    strip.setBrightness(30);                // Set LED brightness 0-255
    colorWipe(strip, strip.Color(24, 100, 100), 1); // Science Glow
    colorWipe(strip_b, strip_b.Color(24, 100, 100), 10); // Science Glow
    colorWipe(strip_c, strip_c.Color(24, 100, 100), 10); // Science Glow
  }
}

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

//Theatre-style crawling lights.
void theaterChase(uint32_t c, uint8_t wait) {
  for (int j = 0; j < 10; j++) { //do 10 cycles of chasing
    for (int q = 0; q < 3; q++) {
      for (uint16_t i = 0; i < strip.numPixels(); i = i + 3) {
        strip.setPixelColor(i + q, c);  //turn every third pixel on
      }
      strip.show();
      delay(50); //chaseing speed
      for (uint16_t i = 0; i < strip.numPixels(); i = i + 3) {
        strip.setPixelColor(i + q, 0);      //turn every third pixel off
      }
    }
  }
}

Ahh I see. I swapped over the LED pins. Pin9 seems to work fine, but Pin6 also blinks. There doesn't seem to be any other pins I can connect the LED's too, so I guess ill just have to wire them both to the same pin.

Thanks I'll give those a try as well. All this is made by whatever I could find mixed together. I barely know what most of it does so i was worried about changing too much.

I tried out that code you posted, but I got errors on the colorWipe parts.

I set the colorWipe back to how I previously had it, and got rid of the delay()'s and its working great now. no more green blinking and its acting the way I want it to.

Thank you so much for all your help blh64!


(I used discord to upload the image because I haven't uploaded an image for a forum for years, let me know if it disappears and you want to see it.)