-
recordShelf rebuild / upgrade
09/22/2017 at 19:36 • 0 commentsI recently moved house and wanted to upgrade my recordShelf as part of the transition. This update will focusly mainly on hardware and IKEA furniture modification.
In my previous google searches looking for IKEA Expedit or Kallax shelves with lighting set-ups I found this page with a beautifully modified shelf with recessed LED strips in each shelf. It looked so much cleaner than my set up and I wanted to emulate it the best I could. The woodworking challenges presented to me were the pretty difficult for me as I've never used a router and I needed to do a lot of routing for this project.
3 weekends back, IKEA had a sale on the particular shelf I was after and I decided it was time to begin this project. I got the shelf, brought it home, opened up the packaging and started to get a plan together.
Routing
To decide on where to put the channel for the LED strip I looked at my old lighting setup and measured how far back I had mounted them. The distance ended up landing between the two holes that receive pegs as part of the shelfs assembly. I covered the line I'd be routing out with blue painters tape to help reduce the amount of chipping of the laminate/veneer.
I then needed to drill holes at an angle from the inside of the LED channel towards the back of the shelf where the wires would run. There were three locations on each shelf/LED strip where wires would attach and run back so I needed three of these holes on each shelf. I only punched through the wrong side by drilling too far on one of the fifteen holes I had to make.
To keep a clean look, I wanted to also route out channels for the wires to run back towards the back of the shelf. This channel would require two passes with the router as I wanted to create a little shoulder or ledge that I could attach a finishing piece to, to hide the wiring. This turned out quite well with the inner channel being just wide enough to accept the 3-wire cable I'm using.
Prepping LED Strips
The LED's I chose are the same that I've been using in past versions of the shelf. WS2812b's with a resolution of 60 pixels per meter. This breaks down to 20 pixels fitting nicely in each individual box of the shelf. I could've just left the strip as one long continuous piece for each shelf but I opted to space out strips of 20 evenly with small jumpers inbetween so that the LED's would fall perfectly between the vertical supports on each horizontal shelf.
Another caveat with the wiring and prepping of the LED strips was that I had to consider the data limitations of the Fadecandy board that I was planning on using. The fadecandy can power up to 512 pixels, 64 per output, 8 outputs. This meant that while one single fadecandy could run all 500 pixels on my shelf, it would cause some really odd runs and daisy chaning together of led strip in order to get the data topology seperated into 8 sections that were less than 64 each. Instead, I opted to add a 2nd fadecandy, and to use 10 seperate data runs that each handled 50 pixels. This meant a more simple wiring scheme with one data line running to the first pixel on each shelf as well as the 51st pixel, exactly in the middle each shelf. To insert a data line into the center of each strip, I cut the full assembled strip in half, and then remade the + and - power connections but didn't bridge the data, instead running a new data line to be inserted at that point.
At this point I needed to test the LED strips using the hidden wiring running through each shelf before moving too much further with assembly. Keep in mind I tested the fresh rolls when they were shipped and they all checked out then, but I checked the strips at many points throughout this build to ensure that all the soldering/wiring I was doing was good.
Silicon Adhesive
With the LED's all checked out, the next step was to permanently adhere the LED strips to the aluminum channel, the aluminum channel to the shelf and all wiring to the shelf. The LED strip was delivered with 3M tape on the back so that was relatively easy to peel off and stick to the inside of the channel. For the aluminum channel I laid down a line of adhesive in the routed out wood, pressed the channel inside, clamped the channel in lightly and cleaned up any excess adhesive that squeezed out the sides. For the wires that run to the back of the shelf I put a bead of adhesive down and then pushed the wiring down into the adhesive covered channel with a glove covered finger to smooth it all out. This worked out extremely well.
Veneer Tape
Next I used yet another new process to help cover the wiring on the shelf. I discovered a product called veneer tape that is a thin roll of wood with pre-glued backing that is meant to finish the raw edges of cabinetry. I cut a strip to fit the channel I had routed out and used a clothes iron with a sheet of aluminum foil between it and the work to warm up the veneer tape's glue. It took a little figuring out but the end result was quite nice.
Lens Cap
The last step of prepping the shelves was to install all the frosted lens caps that will mask the source of the light. When I installed them and turned the lights on, I realized that you could see some of the wiring that was running inside the channel with the LED strip and decided to use some silicon adhesive to clean it up. The end result was definitely as clean as I was hoping it would be.
Power
I then shifted to working out a safe power supply solution. The max DC draw of the 500 pixels at 5v was 30A. I This is what fueled my initial decision to use (2) 20A supplies. These two supplies are wired parallel to AC mains. Each supply has (2) 5v out's. I wired each of the 5v outs through a 10A glass fuse to a terminal block where I will attach the power leads coming off the LED strips. I distributed the LED's as evenly as I could across the (4) 5v 10A outputs I had to work with. All the power equipment was wired together and mounted on a separate piece of wood so I could do this work on my workbench then attach it to the underside of the shelf later.
Shelf Assembly / Wiring
I didn't take any pictures of the normal steps that anyone has seen if they've built IKEA furniture before. Nothing exciting happened then. I just built the shelf face down so I had the side with the wiring facing up for easy access. I routed the wiring out the back of the shelf and out to the sides, keeping it clean with silicon U-brackets I have for mounting LED strip but I think they work well for tidying up the wiring.
At this point, I stood the shelf up and wanted to test the wiring in its current state before wiring and mounting the power supply in its final position. I ended up having a bad data connection! Luckily it was in the center of a strip that was accessible by peeling off the frosted lens cover. I had to do some upside-down soldering, moving a data lead that had ripped off the copper pad from which it was attached directly to one of the leads on the LED's. Here's the best picture I could get of my handy-work. The green cable had to be extended/heat shrunk/attached to the LED (it had been attached to "Din" previously). This is also a good illustration of the silicon adhesive cable management I had done earlier.
Final Power Wiring / Assembly
With everything checked out, I laid the shelf back on it's face and attached the power panel as well as some trendy hairpin legs to the bottom of the shelf and got all the final wiring cleaned up using silicon U clips.
First Full Power Up / Delving into Software
I tested each horizontal shelf individually, testing the power lead at each end of the strip (each individual shelf has a power feed at the beginning and end of the strip) before doing a full power up. Once everything was powered up, I booted up the Raspberry Pi 0 w that I had been using in the previous iteration of the shelf. The first 16 boxes lit up immediately with not problem, as those were the only ones that had been configured in the last version of the shelf (4x4 shelf = 16 boxes, new shelf is 5x5 = 25 boxes). I updated the Fadecandy config file to accommodate the new configuration of LEDs including introducing a second, entirely new, Fadecandy to the setup. After the config was updated, the shelf lit up like a charm.
The following picture was the first full lighting of the shelf that occurred, plus it serves as a good example of how clean the wiring ended up.
Glamour Shots
To Do List
The main item left on the list is to trim/clean up the wiring that terminates at the two Fadecandy boards. I would like to mount these as well as the Raspberry Pi in some sort of visually pleasing manner but I haven't figured that out all the way. I also have a lot of software improvements to work on but for now I thought it was a good place to stop and document the build thus far.
-
Time and Temperature Dashboard
10/27/2016 at 20:59 • 0 commentsAdding some practicality. Dashboard Mode.
A few weeks ago I started looking into other ways I could use this large array of LED's in my living room. I settled on trying to make a dashboard of sorts that displays the current time and temperature.
Time is displayed on the top 12 boxes, 1 full box is equivalent to an hour, each single pixel is equal to 3 minutes.
The color of the completed full hour boxes should be a gradient spread evenly throughout. Every 3 minutes are represented by an orange pixel.
Temperature is displayed in the bottom left hand corner of the shelf. There is a gradient spread out across two boxes that is revealed or hidden as the temperature rises and falls. I have it set to read between 50º-90º Fahrenheit as that seems relevant to my interest in Southern California. 1 pixel = 1º.
All this is handled by a python script that runs on the raspberry pi on boot. Weather is pulled from the openweathermap.org API.
If I want to go back into record selection mode, all I have to do is open the web browser and select a record as per usual. The dashboard script runs once a minute so it will pick back up and start doing it's thing again once you're done picking out a record.
python script below:
#!/usr/bin/env python # Open Pixel Control client: Every other light to solid white, others dark. import opc, time, datetime, sched, json, requests #scheduler for clock s = sched.scheduler(time.time, time.sleep) #opc / LED related setup totalPixels = 320 selectedNo = 0 boxes = [0] * 16 numPixels = 20 client = opc.Client('localhost:7890') darkFrame = (0,0,0) white = (255,255,255) red = (255,0,0) green = (0,255,0) blue = (0,0,255) yuck_green = (115, 147, 126) steel_blue = (160, 185, 198) orange = (245, 166, 91) blankFrame = [ (0,0,0) ] * totalPixels newFrame = blankFrame #reset neopixels to black client.put_pixels(blankFrame) client.put_pixels(blankFrame) time.sleep(0.2) #openweathermaps api setup # replace **OPENWEATHERMAPSAPI_KEY** with your own key.. key = '**OPENWEATHERMAPSAPI_KEY**' #units = 'metric' units = 'imperial' cityid = '5368361' def hex_to_RGB(hex): ''' "#FFFFFF" -> [255,255,255] ''' # Pass 16 to the integer function for change of base return [int(hex[i:i+2], 16) for i in range(1,6,2)] def RGB_to_hex(RGB): ''' [255,255,255] -> "#FFFFFF" ''' # Components need to be integers for hex to make sense RGB = [int(x) for x in RGB] return "#"+"".join(["0{0:x}".format(v) if v < 16 else "{0:x}".format(v) for v in RGB]) def color_dict(gradient): ''' Takes in a list of RGB sub-lists and returns dictionary of colors in RGB and hex form for use in a graphing function defined later on ''' return {"hex":[RGB_to_hex(RGB) for RGB in gradient], "r":[RGB[0] for RGB in gradient], "g":[RGB[1] for RGB in gradient], "b":[RGB[2] for RGB in gradient]} def linear_gradient(start_hex, finish_hex, n): ''' returns a gradient list of (n) colors between two hex colors. start_hex and finish_hex should be the full six-digit color string, inlcuding the number sign ("#FFFFFF") ''' # Starting and ending colors in RGB form s = hex_to_RGB(start_hex) f = hex_to_RGB(finish_hex) # Initilize a list of the output colors with the starting color RGB_list = [s] # Calcuate a color at each evenly spaced value of t from 1 to n for t in range(1, n): # Interpolate RGB vector for color at the current value of t curr_vector = [ int(s[j] + (float(t)/(n-1))*(f[j]-s[j])) for j in range(3) ] # Add it to our list of output colors RGB_list.append(curr_vector) return color_dict(RGB_list) print "Waiting one minute for first result...." def everyMinute(sc): currentTime = datetime.datetime.now() currentHour = currentTime.hour currentMinute = currentTime.minute thirdMinute = round(currentMinute/3) #openweathermap url = requests.get('http://api.openweathermap.org/data/2.5/weather?id='+cityid+'&units='+units+'&APPID='+key) weather = json.loads(url.text) currentTemp = weather['main']['temp'] currentCondition = weather['weather'][0]['description'] print ("Current hour = %s" %currentTime.hour) print ("Current minute = %s" %currentTime.minute) print (currentTemp, "F") print currentCondition temp = int(round(currentTemp)) tempLed = temp-51 print "Rounded Temp : ", temp, " | LED: ", tempLed #24 -> 12 conversion if currentHour > 11: currentHour = currentHour - 12 sunset = linear_gradient("#FC5531","#474A6f", currentHour*20).get('r') sunset = linear_gradient("#FC5531","#474A6f", currentHour*20).get('g') sunset = linear_gradient("#FC5531","#474A6f", currentHour*20).get('b') #reset newFrame every minute newFrame = [ (0,0,0) ] * (totalPixels/4) * 3 #weather pixels weatherFrame = [(0,0,0)] * (totalPixels/8) weatherFrame = [(148,179,255), (148,179,255), (152,182,255), (152,182,255), (160,186,255), (160,186,255), (164,189,255), (164,189,255), (173,196,255), (173,196,255), (180,200,255), (180,200,255), (191,206, 255), (191,206, 255), (203,215,255), (203,215,255), (217,224,255), (217,224,255), (237,235,255), (237,235,255), (255,238,238), (255,238,238), (255,227,211), (255,227,211), (255,213,179), (255,213,179), (255,196,143), (255,196,143), (255, 176, 104), (255, 176, 104), (255,158, 77), (255,158, 77), (255,130, 47), (255,130, 47), (255, 97, 16), (255, 97, 16), (255, 64, 0), (255, 64, 0), (255, 22, 0), (255, 22, 0)] for led, val in enumerate(weatherFrame): #for each if led > tempLed: print led, tempLed weatherFrame[led] = darkFrame del temp del tempLed last2Frames = [(0,0,0)] * (totalPixels/8) weatherFrame.extend(last2Frames) newFrame.extend(weatherFrame) for i,box in enumerate(boxes): #for each box ### hour limit if i <= currentHour: for led, val in enumerate(newFrame): #for each if led > (i*20)-21 and led < (i*20): r = sunset[led] g = sunset[led] b = sunset[led] newFrame[led]=(r, g, b) if led > ((i+1)*20)-21 and led < (((i+1)*20)-21)+thirdMinute+1: newFrame[led]=orange #else: # blankFrame[idx]=(0,0,0) client.put_pixels(newFrame) client.put_pixels(newFrame) time.sleep(0.2) s.enter(60, 1, everyMinute, (sc,)) s.enter(60, 1, everyMinute, (s,)) s.run()
-
June 1, 2016
10/26/2016 at 21:06 • 0 commentsRFID!
I got an RFID reader and hooked it up and got it mostly functioning with the system but I don't use it regularly for a few reasons:
- It runs on a seperate python script from the web interface for record selection and you have to SSH via terminal to start the script. Not elegant by any means.
- It's not 100% accurate or reliable. It may be hard to tell in the video but the 3rd record I scan (At the Drive In) doesn't produce any new blinking LED, but then when I scan a 4th record, the LED for the 3rd record's location shows up. Haven't really looked into why it's not funcitoning correctly.
- I only have 4 sample tags and I'd need to come up with a solution for getting ~1,000 uniquely addressed RFID tags and I haven't done the research into that.
- The whole RFID thing was put into question when a Hackaday user suggested using barcodes instead. That may be more reliable, even if it's less technical and wizard-like.
RFID gear added to system with breadboard and line level shifter :
-
May 14, 2016
10/26/2016 at 05:04 • 0 commentsA major update to the web interface with some minor performance improvements.
Most thorough demonstration of system to date.
-
December 15, 2015
10/26/2016 at 05:02 • 0 commentsMy most advanced version of the system to date is up and running. Now I have a webserver hosting a web interface on the Raspberry Pi that allows a user to connect wirelessly with a device and in a browser, browse through my record collection and select a record. I also started to play with the TouchOSC app and making an interface on an iPad more for busking along to music or making pretty light shows.
These new features were demonstrated in the first video I uploaded about my shelf. This is the first time I'd shared this much about the project with the public.
-
August 19, 2015
10/26/2016 at 04:57 • 0 commentsI move houses. Again.
This time I'm looking to really spruce up the recordShelf setup. I learn about Raspberry Pi's and the Fadecandy board thanks to this lovely tutorial and decide to give those a go. With the previous setup on the Arduino came challenges that I didn't have the patience to tackle. The Fadecandy seemed to help relieve a lot of that stress by providing an easy and reliable control method for the Neopixels.
In addition to changing the shelf configuration I add more LEDs to fully light each of my 16 cubbies bringing the total number of blinking things on my record shelf to 320!
My data and power plans for this step of the project are available for viewing in the instructions section of this project page.
I did a slapdash job of knolling to show off all the new hardware I'd be installing.
Dry run :
Post Install :
-
July 11, 2014
10/26/2016 at 04:31 • 0 commentsHere's a video of the initialization sequence the LED's would go through at power up to see that all three colors of each LED were working correctly.
-
March 16, 2014
10/26/2016 at 04:29 • 0 commentsSmall upgrades happening here and there. I upgraded to an LCD keypad that had both the LCD screen and multiple buttons integrated on one board that seated nicely. It was a much cleaner set up vs the breadboard situation I had before. I also started toying around with different selection animations.
-
Febuary 16, 2014
10/26/2016 at 04:26 • 0 commentsI've made real progress here. I have a basic understanding of how the Neopixels work and I'm forming a solid vision of how my system should work.
Initially the system was set up on an Arduino with an LCD screen and two push buttons. When the system was turned on, the first record's Artist and Title were displayed on the LCD and the first LED would light up. The two buttons allowed you to scroll through a list of my record collection changing the info that was displayed on the LCD as well as what LED was currently lit.
-
December 9, 2013
10/26/2016 at 04:18 • 0 commentsI'm not sure how, but I discover WS2811 LED's and am struck by idea of a record shelf organization/catalog system that utilizes the ability of these newly (to me) discovered individually addressable LED strips.
The first order from Adafruit arrives.
Testing the strip and my deep dive into blinking things begins.