Step 3 - The Case
The case will be a simple design with back and front halves, along with a knob for the click encoder. It will be held together with M3 screws. A mounting method will be discussed in a later post.
The back and front halves are very simple to code, since the hard work has already been done in defining the electronics which is used to "cut" the holes required in the case.
module case_screw_holes(nut_trap=false,z_height=0, dia=lcd_hole_d) {
for(i=[lcd_hole_offset,pl_mounting_hole_x])
for(j=[lcd_hole_offset,pl_mounting_hole2_y]){
if (nut_trap) {
translate([i,j,z_height])
cylinder(r=dia/2, h=shell_width*2, $fn=fn);
translate([i,j,z_height])
cylinder(r=m3_nut_diameter_bigger/2+layer_height*2, h=shell_width, $fn=6);
} else {
translate([i,j,z_height])
cylinder(r=dia/2,h=shell_width*2+30,$fn=12,center=true);
}
}
}
module back() {
difference(){
translate([-shell_width,-shell_width,-shell_width])
cube([pl_x+shell_width*2,pl_y+shell_width*2,shell_split_z+shell_width]);
translate([-clearance,-clearance,-clearance])
cube([pl_x+clearance*2,pl_y+clearance*2,shell_split_z+clearance+0.01]);
LCD_assembly();
case_screw_holes(false,-shell_width);
}
//support pillar
translate([6,6,0])
difference(){
cube([10,10,pl_z+lcd_h_z]);
translate([wall_width,wall_width,0])
cube([10-wall_width*2,10-wall_width*2,pl_z+lcd_h_z+0.1]);
}
}
module front() {
difference(){
translate([-shell_width,-shell_width,shell_split_z])
cube([pl_w+shell_width*2,pl_y+shell_width*2,shell_top-shell_split_z+shell_width]);
translate([-clearance,-clearance,shell_split_z-0.01])
cube([pl_w+clearance*2,pl_y+clearance*2,shell_top-shell_split_z+clearance]);
LCD_assembly();
case_screw_holes(false,shell_top+shell_width);
}
}
The difference() function used in the code above subtracts a cube that is "shell_width" - "clearance" from the overall front or back shell. It then subtracts the LCD_assembly and the case holes. The following two pictures (with elements made transparent/hidden) helps to illustrate the process.
Step 4 - Tweak
The great thing with rapid prototyping is the ability to quickly test out designs and make improvements. The first rough print had a couple of issues:
support for the LCD needed
clearance for the IDC connectors needs moving up
Overall the following issues were noted:
- The holes for the IDC plugs for the cables need to be wider and higher up in the case, easiest to replace with a single cutout.
- The box spacer used as a support in the back interfered with the back of the LCD
- To hold the board more rigidly some supports are required - the corners are the easiest place for these.
Fixes:
Change the IDC header dimensions, only one "header" needed in the model now:
//IDC headers, use the clearance required for the plug
//these are much bigger on z than the actual headers for clearance
idc_y_x=16; //not all will be within case
idc_y_y=37.9;
idc_y_z=6.39+2.5;
idc1_offset_x=128.4;
idc1_offset_y=18.1;
idc1_offset_z=1.61;
Remove the box spacer and add supports to the front and back:
module back() {
side=8; //for the supports
difference(){
union(){
difference(){
translate([-shell_width,-shell_width,-shell_width])
cube([pl_x+shell_width*2,pl_y+shell_width*2,shell_split_z+shell_width]);
translate([-clearance,-clearance,-clearance])
cube([pl_x+clearance*2,pl_y+clearance*2,shell_split_z+clearance+0.01]);
LCD_assembly();
}
//corner supports
for(i=[-wall_width,pl_y-side+wall_width]){
translate([-wall_width,i,-shell_width])
cube([side,side,8.75]);
translate([pl_x-side+wall_width,i,-shell_width])
cube([side,side,4.35]);
}
//additional support
translate([lcd_board_x-side,-wall_width,-shell_width])
cube([side,side/2,8.75]);
}
case_screw_holes(false,0);
}
}
module front() {
side=8; //for the supports
difference(){
union(){
difference(){
translate([-shell_width,-shell_width,shell_split_z])
cube([pl_x+shell_width*2,pl_y+shell_width*2,shell_top-shell_split_z +shell_width]);
translate([-clearance,-clearance,shell_split_z-0.01])
cube([pl_x+clearance*2,pl_y+clearance*2,shell_top-shell_split_z +clearance]);
LCD_assembly();
}
//corner supports
for(i=[-wall_width,pl_x-side+wall_width])
for(j=[-wall_width,pl_y-side+wall_width]){
translate([i,j,shell_split_z])
cube([side,side,shell_top-shell_split_z+wall_width]);
}
//additional supports
for(i=[-wall_width,pl_y-side/2+wall_width]){
translate([lcd_board_x-side,i,shell_split_z])
cube([side,side/2,shell_top-shell_split_z+wall_width]);
}
}
case_screw_holes(false,shell_top+shell_width);
}
}

The final case:
Step 5 - Optional Extras
For models I use often or that go through many iterations where I want to quickly change between different parts it makes sense to simplify the selection of what part of the model to display. At the top of the scad file I have:
///////////////////////////////////////////////////////////
//front, back or Assembly
///////////////////////////////////////////////////////////
side=2; //1 = front, -1 = back 2=printing layout -2 Electronics module 0=assembly model
///////////////////////////////////////////////////////////
This then determines what is rendered using a list of if statements used because, annoyingly, OpenSCAD does not appear to support a "switch" statement.
///////////////////////////////////////////////////////////////////////////////////////
// front
if (side==1)
{
front();
}
// back
else if(side==-1)
{
back();
}
//Printing plate
else if(side==2)
{
translate([shell_width,pl_y*2+shell_width*4,shell_top+shell_width])
rotate([180,0,0])
front();
translate([shell_width,shell_width,shell_width])
back();
translate([pl_y*0.5,pl_y*1.5+shell_width*2,shell_width])
knob_assembly(click_encoder_knob_dia/2);
}
//Electronics
else if(side==-2)
{
LCD_assembly();
}
//assembly
else
{
back();
front();
LCD_assembly();
translate([click_encoder_offset_x,click_encoder_offset_y,wall_width+ click_encoder_shaft_y+click_encoder_z-2])
knob_assembly(click_encoder_knob_dia/2);
}
///////////////////////////////////////////////////////////////////////////////////////
Thus changing one number allows you pick the render you want:
That's all for now - I hope to get a blog post out about the PanelOne itself soon.