Mood light with Arduino Uno and ws2812b Ledstrip

The orginal Design is from Thingyverse. I made some modifications. The top lid can be twisted on with a big thread. I also made a switch on the side to change modes, also added a 10k Potmeter to change the brightness of the light. I did not like the existing patterns so I made some myself (see code). See the thinyverse link for the stl files.

Fusion 360 Design

I used Fusion 360 to modify the other designs to my need. In my design I actualy used the twisted core. Right picture, because is was just easier, and I didn’t have to cut and solder the ledstrip. I modified the original core from 8 rows of 10 LEDS to 6 rows of ten LEDS, so I could use a one meter LED strip.

Original Designs

  • https://www.myminifactory.com/object/3d-print-led-mood-lamp-87393
  • https://www.thingiverse.com/thing:3676533
  • https://www.thingiverse.com/thing:4790221

Thingyverse

https://www.thingiverse.com/thing:5147558

Switch and Potmeter I used for this project

Electrical design

The code

#include "FastLED.h"
#include <EEPROM.h>
#define NUM_LEDS 60 
CRGB leds[NUM_LEDS];
#define PIN 5 
const int sensorValue = analogRead(A1);
#define BUTTON 2
#define MAX_BRIGHTNESS 150      //  Don't set it too high
#define MIN_BRIGHTNESS 7       // set to a minimum of 7%



byte selectedEffect=0;

unsigned long lastDebounceTime = 0;  // the last time the output pin was toggled- gemaakt om geen programma's over te slaan
unsigned long debounceDelay = 300 ;    // the debounce time; increase if the output flickers gemaakt om geen programma's cases over te slaan
void setup()
{
  //delay(3000); // in case we do something stupid. We dont want to get locked out.
  //Serial.begin(9600);
  FastLED.addLeds<WS2811, PIN, GRB>(leds, NUM_LEDS).setCorrection( TypicalLEDStrip );
  int mappedValue = map(sensorValue, 0, 1023, 7, 150);  //hier worden de sensorwaarden omgezet naar Brightness waarden
  FastLED.setBrightness(constrain(mappedValue, MIN_BRIGHTNESS, MAX_BRIGHTNESS)); //hier zetten we de Brightness afhankelijk van de stand van de POTmeter werk alleen bij overschakelen case
  //Serial.println(mappedValue);
  //Serial.println("end");
  pinMode(2,INPUT_PULLUP);  // internal pull-up resistor
  attachInterrupt (digitalPinToInterrupt (BUTTON), changeEffect, CHANGE); // pressed
  
  
  
}

// *** REPLACE FROM HERE ***
void loop() { 
  EEPROM.get(0,selectedEffect); 

  if(selectedEffect>17) { 
    selectedEffect=0;
    EEPROM.put(0,0); 
    
  } 
  
  switch(selectedEffect) {
    
    case 0  : {
                // RGBLoop - no parameters
                RGBLoop();
                
                break;
              }

    case 1  : {
                // colorWipe0 - Color , speed delay kleur draait van beneden naar boven
                colorWipe(0xcc,0x00,0xcc, 50); //paars
                colorWipe(0xff,0xff,0x66, 50); //licht geel
                colorWipe(0x00,0xff,0xff, 50); //lichtblauw
                colorWipe(0xff,0xff,0x66, 50); //licht geel
               
                break;
              }
              
     case 2 : {
                // meteorRain - Color (red, green, blue), meteor size, trail decay, random trail decay (true/false), speed delay wit achtig van beneden naar boven.
                meteorRain(0xff,0xff,0xff,10, 64, true, 30);
               
                break;
              }


   

    case 3  : {
                // tequillasunrise - Color , speed delay kleur draait van beneden naar boven
                colorWipe(0xff,0x00,0x00, 50); //rood
                colorWipe(0xff,0xff,0x00, 50); //geel
                
                
                break;
              }
              
    
              
    case 4  : {
                // NewKITT - Color (red, pink, blue), eye size, speed delay, end pause
                NewKITT(0xff, 0x00, 0x00, 8, 10, 50);
                NewKITT(0xff, 0x00, 0xff, 8, 10, 50);
                NewKITT(0x00, 0x00, 0xff, 8, 10, 50);
                
                break;
              }
              
    case 5  : {
                // Twinkle - Color (red, geel, blue), count, speed delay, only one twinkle (true/false) willekeurige leds gaan aan voorlopig alleen rood
                Twinkle(0xff, 0x00, 0x00, 10, 100, false);
                Twinkle(0xff, 0xff, 0x00, 10, 100, false);
                Twinkle(0x00, 0xff, 0x00, 10, 100, false);
                
                break;
              }
              
    case 6  : { 
                // TwinkleRandom - twinkle count, speed delay, only one (true/false) twinkle van verschillende kleuren
                TwinkleRandom(20, 100, false);
                
                break;
              }
              
    case 7  : {
                // Sparkle - Color (red, green, blue), speed delay
                Sparkle(0xff, 0xff, 0xff, 0);
                
                break;
              }
               
    case 8  : {
                // colorWipe3 - Color , speed delay kleur draait van beneden naar boven
                colorWipe(0xff,0x00,0x00, 50); //rood
                colorWipe(0xff,0x80,0x00, 50); //oranje
                colorWipe(0xff,0xff,0x00, 50); //geel
                colorWipe(0x80,0xff,0x00, 50); //groen
                colorWipe(0x00,0xff,0xff, 50); //lichtblauw
                colorWipe(0x7f,0x00,0xff, 50); //paars
                colorWipe(0xff,0x00,0xff, 50); //roze
                colorWipe(0xff,0x00,0x7f, 50); //lila
                
               
                break;
              }
              
    case 9 : {
                // Running Lights - Color (red, green, blue), wave dealy
                RunningLights(0xff,0x00,0x00, 50);  // red
                RunningLights(0xff,0xff,0xff, 50);  // white
                RunningLights(0x00,0x00,0xff, 50);  // blue
                
                break;
              }
              
    case 10 : {
                // colorWipe - Color  , speed delay kleur draait van beneden naar boven
                colorWipe(0x00,0xff,0x00, 50); //groen
                colorWipe(0xff,0xff,0x66, 50); //licht geel
                colorWipe(0xff,0x80,0x00, 50); //oranje
                colorWipe(0xff,0xff,0x66, 50); //licht geel
                
                break;
              }

    case 11 : {
                // rainbowCycle - speed delay regenboog 
                rainbowCycle(20);
                
                break;
              }

    case 12 : {
                // virgincocktail - Color  , speed delay kleur draait van beneden naar boven
                colorWipe(0x33,0x33,0xff, 50); //blauw
                colorWipe(0x00,0xff,0x00, 50); //groen
                colorWipe(0xff,0xff,0x00, 50); //geel
                colorWipe(0xff,0x00,0x00, 50); //rood
                
                break;
              }

    

    case 13 : {
                // Fire - Cooling rate, Sparking rate, speed delay vuur
                Fire(55,120,15);
                
                break;
              }


    case 14  : {
                // lamp wordt groen
                Naargroen();
                
                break;
              }         

              
    

   
    case 15  : {
                // lamp wordt paars
                Naarpaars();
                
                break;
              }
   case 16  : {
                // lamp wordt rood
                Naarrood();
                
                break;
              }  
   case 17  : {
                // lamp wordt geel
                Naargeel();
                
                break;
              }                                        
  }
}

void changeEffect() {
  if ((millis() - lastDebounceTime) > debounceDelay)
  {
  if (digitalRead (BUTTON) == HIGH) {
    selectedEffect++;
    EEPROM.put(0, selectedEffect);
    asm volatile ("  jmp 0");
  }
}
}

// *************************
// ** LEDEffect Functions **
// *************************

void RGBLoop(){
  for(int j = 0; j < 3; j++ ) { 
    // Fade IN
    for(int k = 0; k < 256; k++) { 
      switch(j) { 
        case 0: setAll(k,0,0); break;
        case 1: setAll(0,k,0); break;
        case 2: setAll(0,0,k); break;
      }
      showStrip();
      delay(3);
    }
    // Fade OUT
    for(int k = 255; k >= 0; k--) { 
      switch(j) { 
        case 0: setAll(k,0,0); break;
        case 1: setAll(0,k,0); break;
        case 2: setAll(0,0,k); break;
      }
      showStrip();
      delay(3);
    }
  }
}

void colorWipe0(byte red, byte green, byte blue, int SpeedDelay) {
  for(uint16_t i=0; i<NUM_LEDS; i++) {
      setPixel(i, red, green, blue);
      showStrip();
      delay(SpeedDelay);
  }
}

void Naargroen() {
  for (int i=1; i<NUM_LEDS; i++) {
    leds[i] = CRGB::Green;
    FastLED.show();
    delay(10);
  }
}

void Naarpaars() {
  for (int i=1; i<NUM_LEDS; i++) {
    leds[i] = CRGB::Purple;
    FastLED.show();
    delay(10);
  }
}

void Naarrood() {
  for (int i=1; i<NUM_LEDS; i++) {
    leds[i] = CRGB::Red;
    FastLED.show();
    delay(10);
  }
}

void Naargeel() {
  for (int i=1; i<NUM_LEDS; i++) {
    leds[i] = CRGB::Yellow;
    FastLED.show();
    delay(10);
  }
}
void colorWipe1(byte red, byte green, byte blue, int SpeedDelay) {
  for(uint16_t i=0; i<NUM_LEDS; i++) {
      setPixel(i, red, green, blue);
      showStrip();
      delay(SpeedDelay);
  }
}



void NewKITT(byte red, byte green, byte blue, int EyeSize, int SpeedDelay, int ReturnDelay){
  RightToLeft(red, green, blue, EyeSize, SpeedDelay, ReturnDelay);
  LeftToRight(red, green, blue, EyeSize, SpeedDelay, ReturnDelay);
  OutsideToCenter(red, green, blue, EyeSize, SpeedDelay, ReturnDelay);
  CenterToOutside(red, green, blue, EyeSize, SpeedDelay, ReturnDelay);
  LeftToRight(red, green, blue, EyeSize, SpeedDelay, ReturnDelay);
  RightToLeft(red, green, blue, EyeSize, SpeedDelay, ReturnDelay);
  OutsideToCenter(red, green, blue, EyeSize, SpeedDelay, ReturnDelay);
  CenterToOutside(red, green, blue, EyeSize, SpeedDelay, ReturnDelay);
}

// used by NewKITT
void CenterToOutside(byte red, byte green, byte blue, int EyeSize, int SpeedDelay, int ReturnDelay) {
  for(int i =((NUM_LEDS-EyeSize)/2); i>=0; i--) {
    setAll(0,0,0);
    
    setPixel(i, red/10, green/10, blue/10);
    for(int j = 1; j <= EyeSize; j++) {
      setPixel(i+j, red, green, blue); 
    }
    setPixel(i+EyeSize+1, red/10, green/10, blue/10);
    
    setPixel(NUM_LEDS-i, red/10, green/10, blue/10);
    for(int j = 1; j <= EyeSize; j++) {
      setPixel(NUM_LEDS-i-j, red, green, blue); 
    }
    setPixel(NUM_LEDS-i-EyeSize-1, red/10, green/10, blue/10);
    
    showStrip();
    delay(SpeedDelay);
  }
  delay(ReturnDelay);
}

// used by NewKITT
void OutsideToCenter(byte red, byte green, byte blue, int EyeSize, int SpeedDelay, int ReturnDelay) {
  for(int i = 0; i<=((NUM_LEDS-EyeSize)/2); i++) {
    setAll(0,0,0);
    
    setPixel(i, red/10, green/10, blue/10);
    for(int j = 1; j <= EyeSize; j++) {
      setPixel(i+j, red, green, blue); 
    }
    setPixel(i+EyeSize+1, red/10, green/10, blue/10);
    
    setPixel(NUM_LEDS-i, red/10, green/10, blue/10);
    for(int j = 1; j <= EyeSize; j++) {
      setPixel(NUM_LEDS-i-j, red, green, blue); 
    }
    setPixel(NUM_LEDS-i-EyeSize-1, red/10, green/10, blue/10);
    
    showStrip();
    delay(SpeedDelay);
  }
  delay(ReturnDelay);
}

// used by NewKITT
void LeftToRight(byte red, byte green, byte blue, int EyeSize, int SpeedDelay, int ReturnDelay) {
  for(int i = 0; i < NUM_LEDS-EyeSize-2; i++) {
    setAll(0,0,0);
    setPixel(i, red/10, green/10, blue/10);
    for(int j = 1; j <= EyeSize; j++) {
      setPixel(i+j, red, green, blue); 
    }
    setPixel(i+EyeSize+1, red/10, green/10, blue/10);
    showStrip();
    delay(SpeedDelay);
  }
  delay(ReturnDelay);
}

// used by NewKITT
void RightToLeft(byte red, byte green, byte blue, int EyeSize, int SpeedDelay, int ReturnDelay) {
  for(int i = NUM_LEDS-EyeSize-2; i > 0; i--) {
    setAll(0,0,0);
    setPixel(i, red/10, green/10, blue/10);
    for(int j = 1; j <= EyeSize; j++) {
      setPixel(i+j, red, green, blue); 
    }
    setPixel(i+EyeSize+1, red/10, green/10, blue/10);
    showStrip();
    delay(SpeedDelay);
  }
  delay(ReturnDelay);
}

void Twinkle(byte red, byte green, byte blue, int Count, int SpeedDelay, boolean OnlyOne) {
  setAll(0,0,0);
  
  for (int i=0; i<Count; i++) {
     setPixel(random(NUM_LEDS),red,green,blue);
     showStrip();
     delay(SpeedDelay);
     if(OnlyOne) { 
       setAll(0,0,0); 
     }
   }
  
  delay(SpeedDelay);
}

void TwinkleRandom(int Count, int SpeedDelay, boolean OnlyOne) {
  setAll(0,0,0);
  
  for (int i=0; i<Count; i++) {
     setPixel(random(NUM_LEDS),random(0,255),random(0,255),random(0,255));
     showStrip();
     delay(SpeedDelay);
     if(OnlyOne) { 
       setAll(0,0,0); 
     }
   }
  
  delay(SpeedDelay);
}

void Sparkle(byte red, byte green, byte blue, int SpeedDelay) {
  int Pixel = random(NUM_LEDS);
  setPixel(Pixel,red,green,blue);
  showStrip();
  delay(SpeedDelay);
  setPixel(Pixel,0,0,0);
}

void colorWipe3(byte red, byte green, byte blue, int SpeedDelay) {
  for(uint16_t i=0; i<NUM_LEDS; i++) {
      setPixel(i, red, green, blue);
      showStrip();
      delay(SpeedDelay);
  }
}

void RunningLights(byte red, byte green, byte blue, int WaveDelay) {
  int Position=0;
  
  for(int i=0; i<NUM_LEDS*2; i++)
  {
      Position++; // = 0; //Position + Rate;
      for(int i=0; i<NUM_LEDS; i++) {
        // sine wave, 3 offset waves make a rainbow!
        //float level = sin(i+Position) * 127 + 128;
        //setPixel(i,level,0,0);
        //float level = sin(i+Position) * 127 + 128;
        setPixel(i,((sin(i+Position) * 127 + 128)/255)*red,
                   ((sin(i+Position) * 127 + 128)/255)*green,
                   ((sin(i+Position) * 127 + 128)/255)*blue);
      }
      
      showStrip();
      delay(WaveDelay);
  }
}

void colorWipe(byte red, byte green, byte blue, int SpeedDelay) {
  for(uint16_t i=0; i<NUM_LEDS; i++) {
      setPixel(i, red, green, blue);
      showStrip();
      delay(SpeedDelay);
  }
}

void rainbowCycle(int SpeedDelay) {
  byte *c;
  uint16_t i, j;

  for(j=0; j<256*5; j++) { // 5 cycles of all colors on wheel
    for(i=0; i< NUM_LEDS; i++) {
      c=Wheel(((i * 256 / NUM_LEDS) + j) & 255);
      setPixel(i, *c, *(c+1), *(c+2));
    }
    showStrip();
    delay(SpeedDelay);
  }
}

// used by rainbowCycle and theaterChaseRainbow
byte * Wheel(byte WheelPos) {
  static byte c[3];
  
  if(WheelPos < 85) {
   c[0]=WheelPos * 3;
   c[1]=255 - WheelPos * 3;
   c[2]=0;
  } else if(WheelPos < 170) {
   WheelPos -= 85;
   c[0]=255 - WheelPos * 3;
   c[1]=0;
   c[2]=WheelPos * 3;
  } else {
   WheelPos -= 170;
   c[0]=0;
   c[1]=WheelPos * 3;
   c[2]=255 - WheelPos * 3;
  }

  return c;
}

void virgincocktail(byte red, byte green, byte blue, int SpeedDelay) {
  for(uint16_t i=0; i<NUM_LEDS; i++) {
      setPixel(i, red, green, blue);
      showStrip();
      delay(SpeedDelay);
  }
}



void Fire(int Cooling, int Sparking, int SpeedDelay) {
  static byte heat[NUM_LEDS];
  int cooldown;
  
  // Step 1.  Cool down every cell a little
  for( int i = 0; i < NUM_LEDS; i++) {
    cooldown = random(0, ((Cooling * 10) / NUM_LEDS) + 2);
    
    if(cooldown>heat[i]) {
      heat[i]=0;
    } else {
      heat[i]=heat[i]-cooldown;
    }
  }
  
  // Step 2.  Heat from each cell drifts 'up' and diffuses a little
  for( int k= NUM_LEDS - 1; k >= 2; k--) {
    heat[k] = (heat[k - 1] + heat[k - 2] + heat[k - 2]) / 3;
  }
    
  // Step 3.  Randomly ignite new 'sparks' near the bottom
  if( random(255) < Sparking ) {
    int y = random(7);
    heat[y] = heat[y] + random(160,255);
    //heat[y] = random(160,255);
  }

  // Step 4.  Convert heat to LED colors
  for( int j = 0; j < NUM_LEDS; j++) {
    setPixelHeatColor(j, heat[j] );
  }

  showStrip();
  delay(SpeedDelay);
}

void setPixelHeatColor (int Pixel, byte temperature) {
  // Scale 'heat' down from 0-255 to 0-191
  byte t192 = round((temperature/255.0)*191);
 
  // calculate ramp up from
  byte heatramp = t192 & 0x3F; // 0..63
  heatramp <<= 2; // scale up to 0..252
 
  // figure out which third of the spectrum we're in:
  if( t192 > 0x80) {                     // hottest
    setPixel(Pixel, 255, 255, heatramp);
  } else if( t192 > 0x40 ) {             // middle
    setPixel(Pixel, 255, heatramp, 0);
  } else {                               // coolest
    setPixel(Pixel, heatramp, 0, 0);
  }
}



void meteorRain(byte red, byte green, byte blue, byte meteorSize, byte meteorTrailDecay, boolean meteorRandomDecay, int SpeedDelay) {  
  setAll(0,0,0);
  
  for(int i = 0; i < NUM_LEDS+NUM_LEDS; i++) {
    
    
    // fade brightness all LEDs one step
    for(int j=0; j<NUM_LEDS; j++) {
      if( (!meteorRandomDecay) || (random(10)>5) ) {
        fadeToBlack(j, meteorTrailDecay );        
      }
    }
    
    // draw meteor
    for(int j = 0; j < meteorSize; j++) {
      if( ( i-j <NUM_LEDS) && (i-j>=0) ) {
        setPixel(i-j, red, green, blue);
      } 
    }
   
    showStrip();
    delay(SpeedDelay);
  }
}

// used by meteorrain
void fadeToBlack(int ledNo, byte fadeValue) {
 #ifdef ADAFRUIT_NEOPIXEL_H 
    // NeoPixel
    uint32_t oldColor;
    uint8_t r, g, b;
    int value;
    
    oldColor = strip.getPixelColor(ledNo);
    r = (oldColor & 0x00ff0000UL) >> 16;
    g = (oldColor & 0x0000ff00UL) >> 8;
    b = (oldColor & 0x000000ffUL);

    r=(r<=10)? 0 : (int) r-(r*fadeValue/256);
    g=(g<=10)? 0 : (int) g-(g*fadeValue/256);
    b=(b<=10)? 0 : (int) b-(b*fadeValue/256);
    
    strip.setPixelColor(ledNo, r,g,b);
 #endif
 #ifndef ADAFRUIT_NEOPIXEL_H
   // FastLED
   leds[ledNo].fadeToBlackBy( fadeValue );
 #endif  
}

// *** REPLACE TO HERE ***



// ***************************************
// ** FastLed/NeoPixel Common Functions **
// ***************************************

// Apply LED color changes
void showStrip() {
 #ifdef ADAFRUIT_NEOPIXEL_H 
   // NeoPixel
   strip.show();
 #endif
 #ifndef ADAFRUIT_NEOPIXEL_H
   // FastLED
   FastLED.show();
 #endif
}

// Set a LED color (not yet visible)
void setPixel(int Pixel, byte red, byte green, byte blue) {
 #ifdef ADAFRUIT_NEOPIXEL_H 
   // NeoPixel
   strip.setPixelColor(Pixel, strip.Color(red, green, blue));
 #endif
 #ifndef ADAFRUIT_NEOPIXEL_H 
   // FastLED
   leds[Pixel].r = red;
   leds[Pixel].g = green;
   leds[Pixel].b = blue;
 #endif
}

// Set all LEDs to a given color and apply it (visible)
void setAll(byte red, byte green, byte blue) {
  for(int i = 0; i < NUM_LEDS; i++ ) {
    setPixel(i, red, green, blue); 
  }
  showStrip();
}