Customized ceiling screen, capable of playing videos, color picker, and color temperature using Raspberry Pi and a web-based GUI.
This project consists of a ceiling mount consisting of 4,661 NeoPixel LEDs powered by a multiple 5V power supply, 10 Fadecandy NeoPixel driver boards and a Raspberry Pi 3 Model B+. This LED ceiling mount is capable of playing videos, and displaying colors as selected on the color picker. A web-based mobile application is developed, so that the users can select the videos or the color, that is to be displayed in the ceiling mount display. The data is sent from the users browser to the the LED ceiling mount over WiFi to the Raspberry pi hosting ROSWWW server. We’ve used ROS framework on this project, to manage multiple nodes and establish communication between Raspberry Pi and the web application.
- Raspberry Pi 3 Model B+ – x 1
- Fadecandy NeoPixel driver boards – x 10
- NeoPixel LED Strip (WS2812b) – 160 metre (approx.)
- Multi TT USB Driver – x 4
- 5V power supply – x 5
- 2-core wires – 1200 metres (power line)
- Cat-6 Cables – 500 metres (data line)
- Polywood base – Diameter 2.9 metres
- Capacitor – 1000µf – 6.3V
- Terminal connector – 85 pcs.
- Wooden board – 6 pcs.
- Bus bar – 36 pcs.
- 3-core wires – 5 metres
- 3-pin plug – 3 pcs.
- Cable ties – 500 (approx.)
- Quality soldering iron
- Soldering lead (lead-free)
- Soldering wick
- Wire stripper
- Wire cutter
- Screw driver
- Cutting player
- CNC machine
- Power drill machine
- Duct tape
- 743 single component instant bonding adhesive
- Flex glue
- Vaccum cleaner
- Woodworking tools (saw, file)
- Spring wire
- Surgical mask and gloves
- Raspberry Pi stretch
- ROS framework
- Open CV
- Fadecandy server
- GL server
Our project included a polywood frame, in a circular shape with a hollow circle close to the bottom of the frame. The frame was designed in such a way it fits into the Plaster of Paris layer on the ceiling. The fitting is done using large mounting screws directly into the concrete layer.
We used flexible NeoPixel strips of 30 LEDs/m. Since, the shape of the frame is circular, placing a whole strip of LED is not a feasible option. We applied some simple mathematical formula to generate a file that would help us determine the amount of LED required in each strip cut.
- Mapping LED, to achieve resolution close to 85 x 85 while playing videos or running color picker. Circle diameter is 2.9 m hence we can accommodate 85 leds maximum,
- To figure out the solution to increase and decrease strip length according to the design of frame and to pull the data and power line at the correct points.
- Dividing power supply lines to the LED strip, so as to evenly distribute the power without creating an overload or led flickering.
To find the solution to these problems, it is important to understand the layout of the frame (fig 1).
Consider a graph of 85×85, the centre of circle lies on the grid (0, 42.5). To fit the LED in circular pattern of the frame, we have to add and remove LED at certain edges, this is the first challenge we faced.
To solve this problem. We designed a text file using python. This text file consisted of (x, y) coordinates, that helped in placement of LEDs. To map the LED for video playing and color picking purpose, we used the same text file to generate tuples using (x, y) coordinates and store those value in a pickle file.
Since, we are using Fadecandy drivers to do this project. Fadecandy can support upto 512 LEDs each, that means on each port of a single Fadecandy driver it can support upto maximum of 64 LEDs. But, since raspberry pi created problem with full 64 led per channel we used only 90% throughput, we decided to keep the amount of LEDs per port to around 60.
The starting point of LED strip varied at different places in our project, because of its unique design. So, we generated a file as tagging system, for us to keep to track of the points at which we will pull power line and data line for the LED.
The File Will Be Attached Below….
Since, we were using 4,661 LEDs in this project. Powering them up was particularly a challenging aspect. There are chances of LED deteriorating during power fluctuations, low voltage, hence we had to be careful and take precautions while powering the LEDs. We used 5, 5V 60A power supplies. Our goal, was to have around 950 LEDs supported by each power supply. The more information about this will be given in brief at power topology section.
In our project, we connected 10 Fadecandy drivers to the Raspberry PI 3 B+, using 2 multi TT USB. Each Multi-TT can support upto 4 Fadecandy drivers, and the other 2 Fadecandy drivers were directly connected to Raspberry PI. Turbo – 4 Port USB Hub is specially designed for high efficient connectivity between multiple devices. It uses mtt (multiple transaction translator technology) which guarantees 12 mbps speed for each port. This enables all 4 devices to operate at 100% efficiency simultaneously. It is vital for Fadecandy to have transfer 12mbps in each port, since we are playing videos in Fadecandy,, high transfer rate was important for us.
In the Raspberry PI we used ROS framework’s ROSWWWW to host the server in local network. We created a responsive HTML page, to give it a mobile web application UX. We used ROSJS library in the webpage to communicate to the ROS server in the Raspberry Pi. Since, ROSJS is capable of sending message through socket protocol. We used this to our advantage to send messages from the Webpage (Browser) to Raspberry pi. Based on the socket messages sent, raspberry pi sends Fadecandy instruction to perform. The snippets of the codes used to perform Fadecandy operations will be explained below.
To distribute power evenly to the multiple LED strips, containing 4,661 LEDs. We used 5 power supply, each power supply containing around 950 LED. Each power supply consisted of 6 bus bar, 3 +Ve and 3 -Ve. The power lines pulled from the LED strips we carefully connected to the bus bar.
We also created a common ground to connect the grounds of Fadecandy and power supply.
The above diagram, accurately show how the power lines, Fadecandy data lines, and ground are connected to each other.
import opc import cv2 import pickle From PIL import Image def video_function(video_name): pix = list() # Locate and add the video file vidcap = cv2.VideoCapture(video_name) success,image = vidcap.read() success = True client = opc.Client('127.0.0.1:7890') #ADDED MAPPED PIXEL mapped_pixel = list() with open('mapped_pixel.pickle', 'rb') as handle: mapped_pixel = pickle.load(handle) Try: while success: success,image = vidcap.read() image = cv2.cvtColor(image,cv2.COLOR_BGR2RGB) pix =  im = Image.fromarray(image) im = im.resize((85,85), Image.ANTIALIAS) # Only want RGB, not RGBA for i in range(0,4661): pix.append(im.getpixel((mapped_pixel[i],mapped_pixel[i]))[:3]) client.put_pixels(pix) time.sleep(1/60) except: print "Video terminated unexpectedly!!"