diff --git a/boxes/__init__.py b/boxes/__init__.py index a7a767c9..382742bf 100755 --- a/boxes/__init__.py +++ b/boxes/__init__.py @@ -581,6 +581,8 @@ def addParts(self, parts): for part in parts: self.addPart(part) + fingerHolesAt : Any + def _buildObjects(self): """Add default edges and parts""" self.edges = {} diff --git a/boxes/generators/matrix.py b/boxes/generators/matrix.py new file mode 100644 index 00000000..97f66ca0 --- /dev/null +++ b/boxes/generators/matrix.py @@ -0,0 +1,371 @@ +# Copyright (C) 2024 fidoriel +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +from boxes import * + + +class Matrix(Boxes): + """WS2812b matrix enclosure""" + + description = """## Simple WS2812b matrix enclosure + WS2812b matrix enclosure for cheap chinease prebuild led matrixes. + This design assumes that the distance between the leds is equal in both directions. + + There are several parts to this design: + - The inner frame to hold the pcb in place + - The front frame to hold a sandwich of plexiglass, spacer and the pcb + - The plexiglass to protect and diffuse the leds. + You may add car tint foil to the plexiglass to achieve a black look + - The spacer to keep the plexiglass from touching the leds + - The back box with an optional mounting hole. Please add a hole for the + power supply to the side panels and the power and data cables + through the led mount frame with your favorite svg editor. + - The side panels with finger joints to hold everything together + + Assembly: + 1. Cut the parts + 2. Assemble the frame (side panels and inner frame) + 3. Insert the pcb, the spacers and the plexiglass + 4. Close the front frame + 5. Insert electronics in the back box + (for example a USB C port on the side panel, a esp32 with wled firmware) + 6. Close the back box + + The inner frame and spacer should keep everything in place without the need for glue. + If you are using multiple modules, + you can add the layout parameters, so that the inner frame adjusts accordingly. + + Please Note: if you are creating a large matrix build of multiple individual modules, + you need to enter absolut values across all modules for all parameters. + Please cut the plane labeled "Plexiglass" out of plexiglass :) + You can use a different thickness for the plexiglass, but make sure to adjust the settings accordingly. + """ + ui_group = "misc" + + led_width: int + led_height: int + pysical_led_y: int + pysical_led_x: int + + distance_between_leds: float + plexiglass_thicknes: float + + h: int + + matrix_back_frame_border: int = 20 + matrix_front_frame_border_offset: int = 10 + + height_pcb: float + + bottom_edge: str = "F" + + mounting_holes: bool + mounting_hole_diameter: float + + matrix_count_x: int + matrix_count_y: int + + def __init__(self) -> None: + Boxes.__init__(self) + self.addSettingsArgs(edges.FingerJointSettings) + + self.argparser.add_argument( + "--led_width", + action="store", + type=int, + default=16, + help="Width of the LED matrix in pixels", + ) + + self.argparser.add_argument( + "--led_height", + action="store", + type=int, + default=16, + help="Height of the LED matrix in pixels", + ) + + self.argparser.add_argument( + "--pysical_led_y", + action="store", + type=int, + default=160, + help="Width of the LED matrix pcb in mm", + ) + + self.argparser.add_argument( + "--pysical_led_x", + action="store", + type=int, + default=160, + help="Height of the LED matrix pcb in mm", + ) + + self.argparser.add_argument( + "--matrix_back_frame_border", + action="store", + type=int, + default=20, + help="Border of the back frame bo keep the pcb in blace but allow for air flow and cable management", + ) + + self.argparser.add_argument( + "--matrix_front_frame_border_offset", + action="store", + type=int, + default=10, + help="Offset of the front frame to allow for the plexiglass to be attached", + ) + + self.argparser.add_argument( + "--distance_between_leds", + action="store", + type=float, + default=1, + help="Distance of the color dividers. Make sure your machine is able to cut thin structures.", + ) + + self.argparser.add_argument( + "--h", + action="store", + type=int, + default=30, + help="Height of the matrix", + ) + + self.argparser.add_argument( + "--height_pcb", + action="store", + type=float, + default=0.2, + help="Height of the pcb including the highest non led components in mm", + ) + + self.argparser.add_argument( + "--plexiglass_thicknes", + action="store", + type=float, + default=3, + help="Thickness of the plexiglass in mm", + ) + + self.argparser.add_argument( + "--mounting_holes", + action="store", + type=boolarg, + default=False, + help="Add mounting holes for the enclosure", + ) + + self.argparser.add_argument( + "--mounting_hole_diameter", + action="store", + type=float, + default=5, + help="Diameter of the mounting holes in mm", + ) + + self.argparser.add_argument( + "--matrix_count_x", + action="store", + type=int, + default=1, + help="Number of modules in x direction", + ) + + self.argparser.add_argument( + "--matrix_count_y", + action="store", + type=int, + default=1, + help="Number of modules in y direction", + ) + + self.buildArgParser() + + def draw_frame(self, sizex: int, sizey: int, posx: int, posy: int): + self.rectangularHole( + x=posx, + y=posy, + dx=sizex, + dy=sizey, + r=0, + center_x=False, + center_y=False, + ) + + def matrix_back_sideholes(self, length: int): + sandwich_height = ( + 2 * self.thickness + self.plexiglass_thicknes + self.height_pcb + ) + h = -0.5 * self.thickness + self.h - sandwich_height + self.fingerHolesAt(0, h, length, angle=0) + + def draw_led_grid(self): + space_per_led_x = self.pysical_led_x / self.led_width + space_per_led_y = self.pysical_led_y / self.led_height + for x in range(self.led_width): + for y in range(self.led_height): + self.rectangularHole( + x=self.matrix_front_frame_border_offset + + (x * space_per_led_x) + + self.distance_between_leds / 2, + y=self.matrix_front_frame_border_offset + + (y * space_per_led_y) + + self.distance_between_leds / 2, + dx=space_per_led_x - self.distance_between_leds, + dy=space_per_led_y - self.distance_between_leds, + r=0, + center_x=False, + center_y=False, + ) + + def create_mounting_holes(self): + if self.mounting_holes: + pos_x = (self.pysical_led_x + 2 * self.matrix_front_frame_border_offset) / 2 + pos_y = ( + (self.pysical_led_y + 2 * self.matrix_front_frame_border_offset) * 3 / 4 + ) + self.rectangularHole( + x=pos_x, + y=pos_y, + dx=self.mounting_hole_diameter, + dy=self.mounting_hole_diameter, + r=self.mounting_hole_diameter, + ) + self.rectangularHole( + x=pos_x, + y=pos_y + self.mounting_hole_diameter / 2, + dx=self.mounting_hole_diameter / 2, + dy=self.mounting_hole_diameter / 2, + r=self.mounting_hole_diameter, + ) + + def render(self): + x, y, h = ( + self.pysical_led_x + 2 * self.matrix_front_frame_border_offset, + self.pysical_led_y + 2 * self.matrix_front_frame_border_offset, + self.h, + ) + + d2 = edges.Bolts(2) + d3 = edges.Bolts(3) + + d2 = d3 = None + + self.rectangularWall( + x, + h, + "FFFF", + bedBolts=[d2] * 4, + move="up", + label="Wall 1", + callback=[ + lambda: self.matrix_back_sideholes( + self.pysical_led_x + 2 * self.matrix_front_frame_border_offset + ) + ], + ) + self.rectangularWall( + y, + h, + "FfFf", + bedBolts=[d3, d2, d3, d2], + move="up", + label="Wall 2", + callback=[ + lambda: self.matrix_back_sideholes( + self.pysical_led_x + 2 * self.matrix_front_frame_border_offset + ) + ], + ) + self.rectangularWall( + y, + h, + "FfFf", + move="up", + bedBolts=[d3, d2, d3, d2], + label="Wall 4", + callback=[ + lambda: self.matrix_back_sideholes( + self.pysical_led_y + 2 * self.matrix_front_frame_border_offset + ) + ], + ) + self.rectangularWall( + x, + h, + "FFFF", + bedBolts=[d2] * 4, + move="up", + label="Wall 3", + callback=[ + lambda: self.matrix_back_sideholes( + self.pysical_led_y + 2 * self.matrix_front_frame_border_offset + ) + ], + ) + + self.rectangularWall( + x, + y, + "ffff", + bedBolts=[d2, d3, d2, d3], + move="right", + label="Top", + callback=[ + lambda: self.draw_frame( + sizex=self.pysical_led_x, + sizey=self.pysical_led_y, + posx=self.matrix_front_frame_border_offset, + posy=self.matrix_front_frame_border_offset, + ) + ], + ) + self.rectangularWall( + x, + y, + "ffff", + bedBolts=[d2, d3, d2, d3], + move="right", + label="Bottom", + callback=[self.create_mounting_holes], + ) + self.rectangularWall( + x, + y, + "ffff", + bedBolts=[d2, d3, d2, d3], + move="right", + label="matrix mount frame, please add cable holes as needed", + ) + + self.rectangularWall( + x, + y, + label="led_grid", + move="right", + callback=[lambda: self.draw_led_grid()], + ) + + self.rectangularWall( + x, + y, + label="led_grid", + move="right", + callback=[lambda: self.draw_led_grid()], + ) + + self.rectangularWall(x, y, label="Plexiglass") diff --git a/examples/Matrix.svg b/examples/Matrix.svg new file mode 100644 index 00000000..427a3c51 --- /dev/null +++ b/examples/Matrix.svg @@ -0,0 +1,694 @@ + + + +Matrix + + +misc - Matrix +boxes Matrix +WS2812b matrix enclosure + +## Simple WS2812b matrix enclosure + WS2812b matrix enclosure for cheap chinease prebuild led matrixes. + This design assumes that the distance between the leds is equal in both directions. + + There are several parts to this design: + - The inner frame to hold the pcb in place + - The front frame to hold a sandwich of plexiglass, spacer and the pcb + - The plexiglass to protect and diffuse the leds. + You may add car tint foil to the plexiglass to achieve a black look + - The spacer to keep the plexiglass from touching the leds + - The back box with an optional mounting hole. Please add a hole for the + power supply to the side panels and the power and data cables + through the led mount frame with your favorite svg editor. + - The side panels with finger joints to hold everything together + + Assembly: + 1. Cut the parts + 2. Assemble the frame (side panels and inner frame) + 3. Insert the pcb, the spacers and the plexiglass + 4. Close the front frame + 5. Insert electronics in the back box + (for example a USB C port on the side panel, a esp32 with wled firmware) + 6. Close the back box + + The inner frame and spacer should keep everything in place without the need for glue. + If you are using multiple modules, + you can add the layout parameters, so that the inner frame adjusts accordingly. + + Please Note: if you are creating a large matrix build of multiple individual modules, + you need to enter absolut values across all modules for all parameters. + Please cut the plane labeled "Plexiglass" out of plexiglass :) + You can use a different thickness for the plexiglass, but make sure to adjust the settings accordingly. + + +Created with Boxes.py (https://festi.info/boxes.py) +Command line: boxes Matrix +Command line short: boxes Matrix + + + + + 100.0mm, burn:0.10mm + + + + + + + + + + + + + + + + + Wall 1 + + + + + + + + + + + + + + + + + Wall 2 + + + + + + + + + + + + + + + + + Wall 4 + + + + + + + + + + + + + + + + + Wall 3 + + + + Top + + + Bottom + + + matrix mount frame, please add cable holes as needed + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + led_grid + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + led_grid + + + Plexiglass + + \ No newline at end of file diff --git a/static/samples/Matrix-thumb.jpg b/static/samples/Matrix-thumb.jpg new file mode 100644 index 00000000..f638ace1 Binary files /dev/null and b/static/samples/Matrix-thumb.jpg differ diff --git a/static/samples/Matrix.jpg b/static/samples/Matrix.jpg new file mode 100644 index 00000000..5b928c01 Binary files /dev/null and b/static/samples/Matrix.jpg differ diff --git a/static/samples/samples.sha256 b/static/samples/samples.sha256 index 45441c26..99dafde5 100644 --- a/static/samples/samples.sha256 +++ b/static/samples/samples.sha256 @@ -174,3 +174,4 @@ f51e3cb0e74e380beda4c0966ee770142ff4fa38c266ca026177f9f4978190a4 ../static/samp 192047afde6a53a10715473e7a3efcf4e11e6d610f5b3fc658c2dfe329304856 ../static/samples/Shadowbox.jpg a0865738425d5d9966dc6975d7e73559bac3c307c9614e8b48bae4abdf3efb5b ../static/samples/BrickSorter-2.jpg 2dcb314cdfa8b136b59288d2f4f7e501b4290ff68560216b6bedd779a32095ad ../static/samples/Shadowbox-diagram.jpg +21333db253007b6e101333826a1231d788cf10e0e2afec84ff2a3f983330091d ../static/samples/Matrix.jpg