Saturday, 19 July 2014

Duet, 20x4 LCD screen and SD card.

Although the Duet communicates over Wifi and I can connect to it with a web browser on my phone, I still get many requests for a LCD based controller. I agree that being able to use a simple controller for quick, common functions is a good idea, things like homing the printer, preheating, starting a print etc. Think3dPrint3d have been providing controllers for older electronics that do this since we started, first with the Panelolu then with the Panelolu2 so it's time to port this to the Duet.

I decided to keep it simple to start with, so rather than get the Panelolu2 working, which would require I2C and headaches with 3.3V and 5V logic, I started with the PanelOne, a very basic LCD, Encoder, SD card combination which we are using on our Kossel Mini Kits.

Using a 5V LCD with 3.3V Microprocessor

This was the first hurdle to overcome. The HD44780 standard that these character LCD displays work on states 2.7 to 5V should work fine for the logic signals, however the LCD screens incorporating these chips are a lot more restrictive: 4.8-5.2V for the logic signals. Given the conflicting information I decided to modify a PanelOne prototype board by hand and give it a go. The key is to keep the logic signals separate from the backlight voltages. The schematic is below:



The major change is the addition of the "VCC" power into pin 2 of the LCD from pin 8 of header P1. Previously this was a straight 5V, now this should be able to be either 5V or 3.3V depending on the logic of the Microprocessor we are interfacing with. I connected this up and edited the "Hello World" sketch within Arduino 1.5.7 (1.5.6 r2 works as well) to use the following pin definitions:
/*
                            Arduino pin number  Duet Pin Name  Expansion header pin
 * LCD RS pin to digital pin D67                 PB16          (32)
 * LCD Enable pin to digital D23                 PA14          (10)
 * LCD D4 pin to digital pin D19                 PA10 RXD0     (14)
 * LCD D5 pin to digital pin D18                 PA11 TXD0     (13)
 * LCD D6 pin to digital pin D17                 PA12 RXD1     (12)
 * LCD D7 pin to digital pin D16                 PA13 TXD1     (11)
*/
LiquidCrystal lcd(67, 23, 19, 18, 17, 16);

Happily this worked!




I tested this with two other LCDs (old generic ones off eBay) and it worked with them as well. However as it's outside the guidelines of the LCD manufacturer's datasheets there is no guarantee that all types of HD44780 character LCDS will work in the same way.

Reading an SD card over SPI

The Duet's build in SD card supports SD2.0 and uses a 4 bit HSMCI interface. However it is often convenient to use an SD card reader mounted next to the screen, so I want to support SD over SPI which is how older 3D printer electronics and hardware interface with SD cards. The Arduino environment has a simple SPI SD library that worked straight away. The only customisation required is to make sure SD.Begin() uses the correct CS pin:

SD.begin(77);

For this example I used the SPI0_NPCS0 pin which is arduino digital pin 77. I combined the listfiles example sketch with the LCD display to list the first 4 files on a SD card:






The code (an adaptation of the listfiles example sketch):


#include <SPI.h>
#include <SD.h>
#include <LiquidCrystal.h>

File root;
// initialize the library with the numbers of the interface pins

LiquidCrystal lcd(67, 23, 19, 18, 17, 16); //RS,E,D4,D5,D6,D7

void setup()
{
  lcd.begin(20, 4);
  lcd.print("Reading Files...");
  delay(2000); //delay or else the message will not be displayed

  if (!SD.begin(77)) {
    lcd.clear();
    lcd.print("initialization");
    lcd.setCursor(0,1);
    lcd.print("failed!");
    return;
  }
   lcd.clear();
   lcd.print("initialization done");
   delay(2000); //delay or else the message will not be displayed
   lcd.clear();
   lcd.print("listing 4 files");
   delay(2000); //delay or else the message will not be displayed
   root = SD.open("/");
   lcd.clear();
   printDirectory(root, 0);
}

void printDirectory(File dir, int numTabs) {
  int row=0;
   while(true) {
     if(row>3) return;
     lcd.setCursor(0,row);
     File entry =  dir.openNextFile();
     if (! entry) {// no more files
       break;
     }
     for (uint8_t i=0; i<numTabs; i++) {
       lcd.print(' ');
     }
     lcd.print(entry.name());
     if (entry.isDirectory()) {
       lcd.print("/");
       printDirectory(entry, numTabs+1);
       row++;
     } else {
       // files have sizes, directories do not
       lcd.print("  ");
       lcd.print(entry.size(), DEC);
       row++;
     }
     entry.close();
   }

}

This sketch, and the adapted Kicad schematic are all on the Think3dPrint3d github.

Next...

I will test more LCD screens and hopefully will be able to get the next batch of PanelOnes compatible with both 3.3V and 5V.

The big job will be to port and adapt the Marlin menu system to RepRap Firmware. If anyone wants to assist with this project then drop me a line and I may be able to help with some hardware (duet board + LCD screen).

Thursday, 26 June 2014

Kossel Mini - feedback and tweaks

After a manic month or so shipping Kossel Mini Kits we have been getting loads of feedback from those building the printer. A lot of the feedback was around the documentation which we have continued to adapt and develop, trying to ensure that if we get asked a question a couple of times we answer it in the documentation. Please keep this feedback coming - we really appreciate it!


Endstop trigger point adjustment


After re-reading minow's very helpful blog on in depth calibration we decided to make a minor change to the endstop trigger function. Previously the endstops triggered on the top of the X,Y and Z carriages:


These have been replaced with slimmer endstop mounts and a modified Delrin V-roller carriage adapter with M2.5 socket cap screw:



This means the endstop trigger point can be finely adjusted in order to level the bed very accurately.

The Delrin V-roller carriage adapter is modified from Haydn Huntley's design, while the slim line endstops are from Johann's original design. The modified files are available on our Github.

The changes can be retrofitted to existing Kossel Minis by simply drilling a hole for the M2.5 to self tap into and printing the thinner endstop mounts. It is fiddly to drill the holes in situ, even using a hand drill, so one Delrin V-roller can be removed to allow the carriage to be removed for easier access. We will shortly publish a new chapter of our Mini Kossel build manual showing this process in detail.


Endstop Trigger point calibration procedure


This process will be incorporated in the manual as soon as we are confident we have explored any downsides to this approach.
The endstops on the X Y and Z pillars should all trigger at the same distance from the bed. This procedure will show how to set these.

Start by using a ruler or measuring tape to set them approximately (within 1mm) at the same distance up the pillars.

Next fine tune each endstop trigger point in turn. This is an iterative process as each adjustment alters the others slightly. First adjust the Z height in the Marlin firmware to a few mm more than it needs to be and upload the firmware:


#define MANUAL_Z_HOME_POS 255


Then work through steps 1-5 below. Note you should do this with the extruder (and heated bed if you have one fitted) at the printing temperature.

  1. Find the X axis endstop trigger point
    1. Home the printer (G28)
    2. Move the extruder to just in front of the X pillar (G1 X-76 Y-43 Z10 F7000). The tip should be approximately 5mm above the bed.
    3. Lower the extruder using Pronterface until a piece of standard 80 gsm printer paper just drags on the nozzle.
    4. Make a note of the Z height using M114:

SENDING:M114

X:-76.00Y:-43.00Z:5.10E:0.00

  1. Adjust the Y axis endstop trigger point
    1. Home the printer (G28)
    2. Move the extruder to just in front of the Y pillar (G1 X76 Y-43 Z10 F7000). The tip should be approximately 5mm above the bed.
    3. Lower the extruder using Pronterface until a piece of standard 80 gsm printer paper just drags on the nozzle.
    4. Check the Z height using M114; the aim to get this to the same value as that recorded for the X axis.
    5. Adjust the M2.5 screw on top of the Y carriage to raise or lower the trigger point (a 360 degree rotation of the M2.5 screw will give a 0.45mm change in trigger point)
    6. Repeat steps a. to e. until the Z height checked in step d. is the same as that recorded for the X axis
  2. Adjust the Z axis trigger point
    1. Follow the same process as step 2, using (G1 X0 Y85 Z4 F7000) to place the extruder in front of the Z pillar
  3. Work around steps 1-3 again because if large changes were required they will noticeably influence the set points of the other axes. Once they are within 0.1mm of each other, move to the next step
  4. Finally we can set the correct “0” point for the centre of the bed.
    1. Home the printer (G28)
    2. Move the extruder to just above the center of the bed (G1 X0 Y0 Z10 F7000)
    3. Lower the extruder using Pronterface until a piece of standard 80 gsm printer paper just drags on the nozzle.
    4. Note the Z height using M114

SENDING:M114

X:0.00Y:0.00Z:5.20E:0.00

  1. Subtract  this Z value from the one set for the manual Z home position at the beginning, change this in the Marlin firmware and re-upload the firmware. In this example it was 255-5.2 = 249.8

#define MANUAL_Z_HOME_POS 249.8
The endstop trigger points are now all within 0.1mm of each other and Z “0” is within 0.1mm of the top of the bed.

The next step is to calibrate the delta radius - Minow's blog outlines the process very well (see step 3).



New Extruder Mount


One of our customers, elmuchacho on thingiverse, has shared a number of designs as upgrades for the Mini Kossel. This is his extruder mount (his picture, then Think3dPrint3d's picture)



This extruder mount holds the extruder more firmly to the frame than the original Think3dprint3d zip tie version. It uses a nut threaded onto the PTFE tube rather than the pushfit connector (top picture).The new mount is shared by elmuchacho on thingiverse and tinkercad. He has also shared a version that uses the pushfit connector supplied with our kits.

To complement this I have reverted part of the extruder block to use the mounting screws and taken the opportunity to make a few other minor tweaks to improve printability - it's also available on the Think3dprint3d github.


Vibration damping


I have noticed a slight chatter in the Traxxas linkages. This is a common issue and the jury is still out on if it noticeably affects the print quality. That said, reducing this definitely makes the printer quieter. One solution is to use rubber bands:



   

These clips were also designed by elmuchacho: http://www.thingiverse.com/thing:371998

Dust is also using a similar idea on his Mini Kossel build (He is not building one of our kits but a similar printer).


Heatbed


We have confirmed the design for the heatbed (Kapton heater on Alu plate with insulation underneath). We are now just waiting for parts to arrive in bulk before we go ahead and offer them for sale. They will be offered at a discount to existing Mini Kossel customers and as an upgrade/stand-alone item as well. The details will follow in a separate blog post.

Sunday, 1 June 2014

Kossel Mini and More




Our Mini Kossel is a version of the excellent Kossel delta robot printer from Johann Rocholl, the designer of the original Rostock delta. It's very quick and easy to put together and relatively economical to source parts for. We have designed some additional parts and incorporated a number of variations from around the community. The changes we have made are described below and all the additional source files are available on Github (look in the T3P3 additions directory)

The Mini Kossel can be bought as a kit or assembled from www.think3dprint3d.com  There are 5 colours in stock or we will print you a set in any custom colour we can source and print. All our parts are printed in ABS on our Mendel90 Lasercut production printers which continue to churn out excellent-quality parts every day after almost a year in service.



Linear Rails v Rollers


The initial Kossel design used linear rails


Picture (c) hiwin.com
These are great but add significantly to the cost. Using rollers on the aluminium extrusions themselves has been suggested in a number of places:

http://www.electronhacks.com/2013/12/kossel-mini-3d-printer-vertical-movement-tutorial/

http://www.thingiverse.com/thing:308369

and this comparison here: http://www.builda3dprinter.eu/rails-wheels/.

These convinced us to try the roller based option. As we are using Mitsumi aluminium extrusions we got Delrin rollers precision machined:



After many hundred of hours printing the bearings and extrusions are not showing visible wear. The only lubrication we have used is a spray of light oil containing PTFE (for example GT85). It is very simple to tighten the adjusting capscrew to adjust the pre-load and take up any slack if they do wear.

Johann is looking into using recirculating Delrin balls directly on the extrusion as well - well worth following up as and when time permits. Delrin balls are quite pricey, though, but it would be awesome if Airsoft BB pellets turned out to work well. The best carriage for these turned out to be Haydn Huntley's.


RepRapPro mini extruder


This extruder has been proven over many thousands of hours, both on RepRapPro's Mendel and Huxley printers and on our Mendel90 Lasercut multi extruder machine.



We modified this slightly to use easily obtainable pushfit bowden fittings and made a our own version of the quick and simple zip tie mount to fit to the extrusion:






Power and electronics mountings

To keep the kit as simple and user friendly as possible we designed a USB and power plug plate:


That provides a neat interface with the RAMPS in the base of the printer. The non-heated bed version uses a single 5 amp laptop style power supply. We are investigating options for the heated bed version but one being considered is an extension of this plate with another plug for a heated bed power supply. The RAMPS is mounted on another simple plate:


The picture also shows some simple tabs to keep a round glass mirror plate fixed securely using M3 penny washers.



Filament management

A reel holder and filament guide complete the kit:


Build Manual

We have written a comprehensive Kossel Mini Assembly Manual for the kit which we hope will become a useful resource for all. We would really welcome feedback on the manual and suggestions for additional information to add. 

Prints

One of the Mini Kossel beta testers did these prints of the EggO egg "thrones" by mageli which are awesome. 




PanelOne LCD

Following on from the case design tutorial in SCAD here is more information of the PanelOne, a simple LCD controller for RAMPS. It is optimised for those who want to rout/etch a single sided PCB with only through-hole components. It also uses widely-available 10-way IDC ribbon cables.




The more fiddly elements of the SD card socket and logic level converter are left to an optional, and generally available, daughter board such as this one from adafruit:


image from adafruit.com
or this one:
image from hobbytonics.co.uk

The circuit board itself is designed in KiCAD as a single sided board, and was originally designed for Sumpod who commissioned us to design a board that could be routed on a PCB mill and fitted the dimensions of their printer enclosure.



In keeping with the simplicity of the design there is no adaptor board required at the RAMPS end as the pinouts are arranged to match with the AUX2 and AUX3 headers.



The complete KiCad files for the PanelOne are available on github.

Coming Soon

Watch this space... we are working on adding a heated bed and an interesting twist on multiple extruders!

Friday, 25 April 2014

Using OpenSCAD to design a basic LCD enclosure

Regular readers will be aware I am a big fan of using scripted CAD, specifically OpenSCAD, as a design tool. I have gone into my reasoning before, which I won't repeat now. This is a further worked example showing the steps I took to design a case for a basic LCD+Click encoder controller for a 3d printer. This posts will try not to repeat too much ground covered in my previous OpenSCAD "How To": the OpenSCAD manual will help following along.

As always this is Open Source Hardware so the OpenSCAD source and supporting control knob file is shared on GitHub.


The electronics to encase


The PanelOne is a simple back board for a 20x4 character LCD with a encoder, a SD card board and brightness and contrast pots. I will go into the rationale and design of it in another post.



The aim for the case is to be quick and easy to print and use the the minimum of additional screws and other fixings.

Step 1 - Measurements


First step is to take measurements of the dimensions of the electronics - these can be taken from the CAD files if you have them:


This shows using the dimension function in KiCAD, although you can read the co-ordinates directly. The other, and my preferred, option is to take direct measurements:


This allows for the effect of the assembly processes to be taken into account easily.

Step 2 - Model the Electronics


Depending on how complex a case you are making, this step can be very simple or very complex. For a great example of how complex a circuit model model can be, check out UrielGuy's model of the Sanguinololu electronics


In this case I am going to keep it simple.

Start by assigning the measurements to variables - you will thank yourself many times over as you come to reuse or modify these.:

clearance=0.8;
wall_width=1.6; //minimum wall width //should be a multiple of your extruded dia
layer_height=0.2;

//LCD screen
lcd_scrn_x=99;
lcd_scrn_y=40.5;
lcd_scrn_z=9.4;

lcd_board_x=99;
lcd_board_y=61;
lcd_board_z=1.6; //does not include metal tabs on base

lcd_hole_d=3.4;
lcd_hole_offset=(lcd_hole_d/2)+1;

//board edge to center of first connector hole
lcd_connect_x=10.2;
lcd_connect_y=58.4;

//PanelOne circuit board
pl_x=136;
pl_y=lcd_board_y;
pl_z=4; //excluding click Encoder and SD card and cable headers, but including the soldered bottoms of the through hole connectors
pl_mounting_hole_dia=3.4;
pl_mounting_hole_x=133.6;
pl_mounting_hole1_y=3.4; //only bothering with 2 holes at this point
pl_mounting_hole2_y=58.4;

//rotary encoder
click_encoder_x=13.2;
click_encoder_y=12.6;
click_encoder_z=6;
click_encoder_shaft_dia=6.9+clearance;
click_encoder_shaft_h=12.2;
click_encoder_knob_dia=24;
click_encoder_offset_x=112.2;
click_encoder_offset_y=30.8;


//contrast and brightness holes
cb_dia=4; //hole diameter for adjustment screw
cb_h=15;
con_offset_x=107.2;
con_offset_y=16.1;
con_offset_z=pl_z;
bri_offset_x=117.1;
bri_offset_y=16.0;
bri_offset_z=con_offset_z;

//headers
//lcd connection header
lcd_h_x=(16*2.54)+2.54;
lcd_h_y=2.54;
lcd_h_z=3; //this is the gap between the circuit board caused by the plastic spaces on 2.54mm headers
lcd_h_offset_x=lcd_connect_x;
lcd_h_offset_y=lcd_connect_y;
lcd_h_offset_z=pl_z;

//IDC headers, use the clearance required for the plug
//these are much bigger on z than the actual headers for clearance
idc_h_x=16; //not all will be within case
idc_h_y=14+clearance;
idc_h_z=pl_z+click_encoder_z;
idc1_offset_x=128.4;
idc1_offset_y=20.5-clearance/2;
idc1_offset_z=-wall_width;
idc2_offset_x=idc1_offset_x;
idc2_offset_y=39.6-clearance/2;
idc2_offset_z=idc1_offset_z;

//SD card slot
SD_slot_x=24.5+clearance; //wider for clearance
SD_slot_y=29.5;
SD_slot_z=4;
SD_slot_offset_x=100.5-clearance/2;
SD_slot_offset_y=39.5;
SD_slot_offset_z=pl_z;

//case variables
shell_split_z = pl_z+SD_slot_z; //board split in the top of the slots
shell_width=wall_width+clearance;

shell_top = pl_z+click_encoder_z+2;

Then I write a number of small functions to draw up the components:

module LCD_assembly() {
    translate([0,0,lcd_h_offset_z+lcd_h_z])
        lcd();
        pl_board();
   //lcd connection header
    color("black")
        translate([lcd_h_offset_x,lcd_h_offset_y,lcd_h_offset_z])
            cube([lcd_h_x,lcd_h_y,lcd_h_z]);
}

//LCD screen
module lcd() {
    difference(){
        union(){
            color("OliveDrab")
                translate([0,0,0])
                    cube([lcd_board_x,lcd_board_y,lcd_board_z]);
            color("DarkSlateGray")
                translate([(lcd_board_x-lcd_scrn_x)/2,(lcd_board_y-lcd_scrn_y)/2,lcd_board_z])
                    cube([lcd_scrn_x,lcd_scrn_y,lcd_scrn_z]);
        }
        for(i=[lcd_hole_offset,lcd_board_x-lcd_hole_offset]){
            for(j=[lcd_hole_offset,lcd_board_y-lcd_hole_offset]){
                translate([i,j,lcd_board_z])
                    cylinder(r=lcd_hole_d/2,h=lcd_board_z+3,$fn=12,center=true);
            }
        }
    }
}

//PanelOne circuit board simplified
module pl_board() {
    difference(){
        union(){
            color("lightgreen")cube([pl_x,pl_y,pl_z]);
            //click encoder
            color("darkgrey"){
                translate([click_encoder_offset_x,click_encoder_offset_y,pl_z+(click_encoder_z)/2])
                    cube([click_encoder_x,click_encoder_y,click_encoder_z],center=true);
                translate([click_encoder_offset_x,click_encoder_offset_y,pl_z+click_encoder_z+(click_encoder_shaft_h)/2])
                    cylinder(r=click_encoder_shaft_dia/2,h=click_encoder_shaft_h,center=true);
            //contrast and brightness pots
                  translate([con_offset_x,con_offset_y,con_offset_z+cb_h/2])
                    cylinder(r=cb_dia/2,h=cb_h,center=true);
                  translate([bri_offset_x,bri_offset_y,bri_offset_z+cb_h/2])
                    cylinder(r=cb_dia/2,h=cb_h,center=true);
            }        
        }
        translate([-0.1,-0.1,-0.1]){
            cube([93,45,pl_z+2]);
            cube([6,lcd_board_y+1,pl_z+2]);
        }
        //mounting holes
        translate([pl_mounting_hole_x,pl_mounting_hole1_y,(pl_z+3)/2])
            cylinder(r=pl_mounting_hole_dia/2,h=pl_z+3,center=true);
        translate([pl_mounting_hole_x,pl_mounting_hole2_y,(pl_z+3)/2])
            cylinder(r=pl_mounting_hole_dia/2,h=pl_z+3,center=true);
    }
    //SD board 
    color("lightblue")    
        translate([SD_slot_offset_x,SD_slot_offset_y,SD_slot_offset_z]) 
            cube([SD_slot_x,SD_slot_y,SD_slot_z]);
   //IDC headers
    color("darkgrey"){
        translate([idc1_offset_x,idc1_offset_y,idc1_offset_z])
            cube([idc_h_x,idc_h_y,idc_h_z]);
        translate([idc2_offset_x,idc2_offset_y,idc2_offset_z])
            cube([idc_h_x,idc_h_y,idc_h_z]);
    }
}



It is a good idea to split down the design into logical blocks - these can be reused. The LCD module is re-used from the Panelolu2 case design for example.

I used the color function within OpenSCAD to make this render easier to view:

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 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.