Neopixel addressable LEDs

LEDs! Bright, colourful fun things that are often seen as tacky, or simple – but that just means you haven’t experimented with the nature of light itself!

In this recipe we are dealing with addressable LED strips. These are very different to 12V RGB LED strips.

NeoPixels are also known as WS2812B pixels. NeoPixel is the ‘brand’ given by Adafruit, a popular electronic prototyping store based in New York City, US. WS2812B is the actual part number of the addressable LED chips. They operate at 5VDC and will not do well if over/underpowered.

A crucial differentiator between these RGB strips and ‘addressable’ versions (the NeoPixels, WS2812B etc) is that you can change the colour output of a 12V RGB strip ALL AT ONCE, but not individually. That’s where the ‘addressable’ part of NeoPixels come in.

For more information on NeoPixels, check the Neopixel Überguide here.

You might also have come across DotStar addressable LEDs, which use the APA102C chipset. A cheaper knockoff version of the APA102C is the SK9822. All of these different addressable LED technologies will require a a library that supports driving them. Once you get past the basics, you might be interested in the more versatile and full-featured FastLED library as an all-in-one solution for driving any of these addressable LED pixels.

A typical Neopixel will draw up to 60mA (0.06A). An 8-Neopixel stick will draw up to 480mA (0.48A) at full white brightness. Just like the 12V RGB LED strips, power consumption adds up, so make sure you choose the right 5V power supply. We’ll just get by with the USB port’s 500mA in this recipe, but you definitely want to use either a wall-wart transformer, or one of those USB portable power banks for your phones if you want a more robust setup.

You can swap out the light sensor with any other analog sensor in your kit, so long as you modify the code to suitably adjust the scaling of the sensor readings in relation to the desired output.

The code is getting the ambient light sensor to alter the speed at which the trippy rainbow animation is cycling. The scope of programming complex colour shifts might be too big to handle here, but follow this useful library guide as a good start. We can talk more about writing more specific code in class, as needed.


Libraries Used

(learn how to import them in the Build IDE):


Code

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
// This #include statement was automatically added by the Particle IDE.
#include <neopixel.h>

// IMPORTANT: Set pixel COUNT, PIN and TYPE
#define PIXEL_PIN D0
#define PIXEL_COUNT 8
#define PIXEL_TYPE WS2812B

Adafruit_NeoPixel strip = Adafruit_NeoPixel(PIXEL_COUNT, PIXEL_PIN, PIXEL_TYPE);

// code in this setup function runs just once, when Photon is powered up or reset
void setup() {
    Serial.begin(9600);             // Open a connection via the Serial port – useful for debugging

    pinMode(D0, OUTPUT);            // goes to Neopixel stick

    strip.begin();
    strip.show(); // Initialize all pixels to 'off'

    delay(5000);                    // Common practice to allow board to 'settle' after connecting online
}


void loop() {
    updateLED();
}


void updateLED() {

    // in this example we use a simple light sensor on A0 to drive the Neopixels
    int sensorReading = analogRead(A0);

    int scaled = map(sensorReading, 700, 1700, 0, 255);   // tweak these numbers accordingly!
    scaled = constrain(scaled, 0, 255);                   // make sure scaled ranged is kept within range

    colorAll(strip.Color(0, 0, scaled), 1);

    Serial.println(scaled);
    // rainbow(scaled);
}


// Set all pixels in the strip to a solid color, then wait (ms)
void colorAll(uint32_t c, uint8_t wait) {
  uint16_t i;

  for(i=0; i<strip.numPixels(); i++) {
    strip.setPixelColor(i, c);
  }
  strip.show();
  delay(wait);
}

// Fill the dots one after the other with a color, wait (ms) after each one
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);
  }
}


void rainbow(uint8_t wait) {
  uint16_t i, j;

  for(j=0; j<256; j++) {
    for(i=0; i<strip.numPixels(); i++) {
      strip.setPixelColor(i, Wheel((i+j) & 255));
    }
    strip.show();
    delay(wait);
  }
}

// Input a value 0 to 255 to get a color value.
// The colours are a transition r - g - b - back to r.
uint32_t Wheel(byte WheelPos) {
  if(WheelPos < 85) {
   return strip.Color(WheelPos * 3, 255 - WheelPos * 3, 0);
  } else if(WheelPos < 170) {
   WheelPos -= 85;
   return strip.Color(255 - WheelPos * 3, 0, WheelPos * 3);
  } else {
   WheelPos -= 170;
   return strip.Color(0, WheelPos * 3, 255 - WheelPos * 3);
  }
}