This desk lamp is designed with WS2812b (neopixels https://www.amazon.com/ ) any LED density will work, but you could use RGBs if you want.
I designed the bases to use ATTINY85s. https://www.amazon.com/ (The base with a battery can fit either model of the Attiny85s)
The version with the battery uses any 3.7 lipo battery ( I used these https://www.amazon.com/), and a lipo charger with battery protection https://www.amazon.com/ (either type-c or micro-usb)
I made a stem for the model to print or you can use PTFE tube https://www.amazon.com/ or metal tubing https://www.amazon.com/ , just cut to desired length.
The power switch I used was https://www.amazon.com/
There are 2 models one that uses a 2 position switch ( for brightness) https://www.amazon.com/ and a 3 position switch ( for brightness and pausing effect) https://www.amazon.com/
OTHER STUFF NEEDED
HOW TO BUILD
WIRING POWER (with Battery)

WIRING POWER (without Battery)
PROGRAMING THE ATTINY85
You'll need to download Arduino IDE https://www.arduino.cc/en/software . Once you have it installed you'll need to add 2 libraries to the adruino IDE program. The Adafruit Neopixel Library and Digistump Library (http://digistump.com/package_digistump_index.json)
Here is my code I used, just edit the number of LEDs so it matches what you used. To program the Attiny85 make sure you have the 2 Arduino libraries. Simply add the code, chose board: Digispark (Default - 16.5mhz) and hit Upload WITHOUT having the Attiny85 plugged in. Plug in when prompted to.
#include <Adafruit_NeoPixel.h>#ifdef __AVR__#include <avr/power.h> // Required for 16 MHz Adafruit Trinket#endif#define LED_PIN 3#define LED_PIN2 4
// How many NeoPixels are attached to the Arduino?#define LED_COUNT 45#define LED_COUNT2 45
Adafruit_NeoPixel strip(LED_COUNT, LED_PIN, NEO_GRB + NEO_KHZ800);Adafruit_NeoPixel strip2(LED_COUNT2, LED_PIN2, NEO_GRB + NEO_KHZ800);
void setup() { #if defined(__AVR_ATtiny85__) && (F_CPU == 16000000) clock_prescale_set(clock_div_1); #endif strip.begin(); strip.show(); // Initialize all pixels to 'off' strip.setBrightness(50); // Set BRIGHTNESS to about 1/5 (max = 255) strip2.begin(); strip2.show(); // Initialize all pixels to 'off' strip2.setBrightness(150); // Set BRIGHTNESS to about 1/5 (max = 255) colorWipe(strip.Color(255, 255, 255), 100); colorWipe(strip2.Color(255, 255, 255), 100); }
void loop() { colorWipe(strip.Color(255, 0, 0), 50); // Red colorWipe(strip.Color(150, 150, 0), 50); // Yellow colorWipe(strip.Color( 0, 255, 0), 50); // Green colorWipe(strip.Color( 0, 150, 150), 50); // Cyan colorWipe(strip.Color( 0, 0, 255), 50); // Blue colorWipe(strip.Color( 150, 0, 150), 50); // Purle rainbow(25); rainbowCycle2(50); rainbowCycle(30); rainbowCycle3(2);}
void colorWipe(uint32_t color, int wait) { for(int i=0; i<strip.numPixels(); i++) { // For each pixel in strip... strip.setPixelColor(i, color); // Set pixel's color (in RAM) strip2.setPixelColor(i, color); // Set pixel's color (in RAM) strip.show(); // Update strip to match strip2.show(); // Update strip to match delay(wait); // Pause for a moment }}
void rainbow(uint8_t wait) { uint16_t i, j;
for(j=0; j<256*5; j++) { for(i=0; i<strip.numPixels(); i++) { strip.setPixelColor(i, Wheel((i+j) & 255)); strip2.setPixelColor(i, Wheel((i+j) & 255)); } strip.show(); strip2.show(); delay(wait); }}
// Slightly different, this makes the rainbow equally distributed throughoutvoid rainbowCycle2(uint8_t wait) { uint16_t i, j;
for(j=0; j<256*5; j++) { // 5 cycles of all colors on wheel for(i=0; i< strip2.numPixels(); i++) { strip.setPixelColor(i, Wheel(((i * 256 / strip.numPixels()/4) + j) & 255)); strip2.setPixelColor(i, Wheel(((i * 256 / strip2.numPixels()/4) + j) & 255)); } strip.show(); strip2.show(); delay(wait); }}
// Slightly different, this makes the rainbow equally distributed throughoutvoid rainbowCycle(uint8_t wait) { uint16_t i, j;
for(j=0; j<256*5; j++) { // 5 cycles of all colors on wheel for(i=0; i< strip.numPixels(); i++) { strip.setPixelColor(i, Wheel(((i * 256 / strip.numPixels()) + j) & 255)); strip2.setPixelColor(i, Wheel(((i * 256 / strip2.numPixels()) + j) & 255)); } strip.show(); strip2.show(); delay(wait); }}
// Slightly different, this makes the rainbow equally distributed throughoutvoid rainbowCycle3(uint8_t wait) { uint16_t i, j;
for(j=0; j<256*25; j++) { // 30 cycles of all colors on wheel for(i=0; i< strip.numPixels(); i++) { strip.setPixelColor(i, Wheel(((i * 256 / strip.numPixels()/2) + j) & 255)); strip2.setPixelColor(i, Wheel(((i * 256 / strip2.numPixels()/2) + j) & 255)); } strip.show(); strip2.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) { WheelPos = 255 - WheelPos; if(WheelPos < 85) { return strip.Color(255 - WheelPos * 3, 0, WheelPos * 3); } else if(WheelPos < 170) { WheelPos -= 85; return strip.Color(0, WheelPos * 3, 255 - WheelPos * 3); } else { WheelPos -= 170; return strip.Color(WheelPos * 3, 255 - WheelPos * 3, 0); }}
I can make more lenses, just comment some ideas.
The author marked this model as their own original creation.