2 //*************************************************************//
\r
3 // [EN] --- DIGITAL SUNDIAL
\r
4 // [FR] --- CADRAN SOLAIRE NUMERIQUE
\r
5 //*************************************************************//
\r
8 // website: www.mojoptix.com
\r
9 // Email: julldozer@mojoptix.com
\r
10 // Date: 13 october 2015
\r
11 // License: Creative Commons CC-BY (Attribution)
\r
13 //*************************************************************//
\r
14 // Optimized by Margu on 24 november 2015
\r
15 //*************************************************************//
\r
17 // [EN] The episode #001 of the video podcast Mojoptix describes this sundial in details:
\r
18 // http://www.mojoptix.com/fr/2015/10/12/ep-001-cadran-solaire-numerique
\r
22 // [FR] L'episode #001 du podcast video mojoptix decrit ce cadran solaire en detail:
\r
23 // http://www.mojoptix.com/fr/2015/10/12/ep-001-cadran-solaire-numerique
\r
26 //*************************************************************//
\r
29 // Choose what you want to print/display:
\r
31 // 2: the central connector piece
\r
32 // 3: the top part of the lid
\r
33 // 4: the bottom part of the lid
\r
34 // 10: display everything
\r
37 FLAG_northern_hemisphere = 1; // set to 1 for Northen Hemisphere, set to 0 for Southern Hemisphere
\r
39 FLAG_gnomon_brim = 0; // Add a brim to the gnomon
\r
40 FLAG_bottom_lid_support = 1; // Add some support structure for the lid teeth
\r
44 /* ************************************************************************/
\r
45 /* PARAMETERS *************************************************************/
\r
46 /*************************************************************************/
\r
47 epsilon_thickness = 0.02; // used to ensure openscad is not confused by almost identical surfaces
\r
49 gnomon_brim_thickness = 0.3;
\r
50 gnomon_brim_width = 10;
\r
51 gnomon_brim_gap = 0.1;
\r
53 FLAG_mirror_x_characters = 1; // set to 0 if viewing directly the characters on the blocks, set to 1 if viewing their reflection of a surface
\r
55 gnomon_radius = 30; // (change at your own risks !)
\r
57 pixel_size_x = gnomon_radius*8.0/40.0;
\r
58 pixel_size_y = gnomon_radius*1.0/40.0;
\r
59 pixel_pitch_x = gnomon_radius*10.0/40.0;
\r
60 pixel_pitch_y = gnomon_radius*10.0/40.0;
\r
62 grid_pixel_depth = 0.1;
\r
64 nn = 40.0/gnomon_radius;
\r
66 /* ************************************************************************/
\r
67 /* FONT *******************************************************************/
\r
68 /* ************************************************************************/
\r
69 /* index in the array 0 1 2 3 4 5 6 7 8 9 10 11 12
\r
70 Characters: 0 1 2 3 4 5 6 7 8 9 : {full white} {full dark}
\r
72 1st coordinate in the array: the index in the array (see above)
\r
73 2nd coordinate in the array: the Y (!!) coordinate
\r
74 3nd coordinate in the array: the X coordinate
\r
76 font_nb_pixel_x = 4; // 4 pixels wide
\r
77 font_nb_pixel_y = 6; // 6 pixels high
\r
80 [0,1,1,0], //index 0: character "0"
\r
87 [0,1,0,0], //index 1: character "1"
\r
94 [0,1,1,0], //index 2: character "2"
\r
101 [0,1,1,0], //index 3: character "3"
\r
108 [1,0,0,1], //index 4: character "4"
\r
115 [1,1,1,1], //index 5: character "5"
\r
122 [0,1,1,1], //index 6: character "6"
\r
129 [1,1,1,1], //index 7: character "7"
\r
136 [0,1,1,0], //index 8: character "8"
\r
143 [0,1,1,0], //index 9: character "9"
\r
150 [0,0,0,0], //index 10: character ":"
\r
157 [1,1,1,1], //index 11: character {full white}
\r
164 [0,0,0,0], //index 12: character {full dark}
\r
171 // Added by Margu : we add some "characters" to display the transitions
\r
172 // "0"-"1" transition character has pixels lit only if both corresponding digits are lit (boolean And operation)
\r
175 [0,1,0,0], //index 13: character {"0" to "1" transition}
\r
182 [0,1,0,0], //index 14: character {"1" to "2" transition}
\r
189 [0,1,1,0], //index 15: character {"2" to "3" transition}
\r
196 [0,0,0,0], //index 16: character {"3" to "4" transition}
\r
203 [1,0,0,1], //index 17: character {"4" to "5" transition}
\r
210 [0,1,1,1], //index 18: character {"5" to "6" transition}
\r
217 [0,1,1,1], //index 19: character {"6" to "7" transition}
\r
224 [1,1,1,1], //index 20: character {"7" to "8" transition}
\r
225 [0,0,0,1], // not used, so wrong values !!!
\r
231 [0,1,1,0], //index 20: character {"8" to "9" transition}
\r
232 [1,0,0,1], // not used, so wrong values !!!
\r
238 [0,1,1,0], //index 22: character {"9" to "0" transition}
\r
245 [0,1,1,0], //index 23: character {"0" to "2" transition}
\r
252 [0,0,0,0], //index 24: character {"2" to "4" transition}
\r
259 [0,0,0,0], //index 25: character {"4" to "0" transition}
\r
269 /* ************************************************************************/
\r
270 /* MODULES ****************************************************************/
\r
271 /* ************************************************************************/
\r
273 /* ************************************************************************/
\r
274 module extrude_pixel(direction_angle_x,direction_angle_y, pixel_wall_angle_x, pixel_wall_angle_y) {
\r
275 /* Extrude a pixel in a given direction.
\r
277 direction_angle_x: extrusion angle (from the normal to the pixel) in the x direction
\r
278 direction_angle_y: extrusion angle (from the normal to the pixel) in the y direction
\r
279 Return a (positive) solid that can then be substracted from another solid
\r
280 (Origin at the center of the base pixel)
\r
282 // compute geometry
\r
283 top_pixel_location_z = 2*gnomon_radius; // ie: somewhere outside the gnomon
\r
284 // top_pixel_location_x = top_pixel_location_z * tan(direction_angle_x);
\r
285 // top_pixel_location_y = top_pixel_location_z * tan(direction_angle_y);
\r
286 top_pixel_size_x = pixel_size_x +2*top_pixel_location_z*tan(pixel_wall_angle_x); // account for the non_vertical pixel walls
\r
287 top_pixel_size_y = pixel_size_y +2*top_pixel_location_z*tan(pixel_wall_angle_y);
\r
288 // build (positive) geometry: extrude vertically then rotate
\r
289 union() { rotate([direction_angle_y,direction_angle_x,0]) // rotate the whole extrusion in the chosen direction
\r
291 rotate([-direction_angle_y,-direction_angle_x,0]) // derotate the base pixel (to keep it flat at the bottom)
\r
292 cube([pixel_size_x,pixel_size_y,epsilon_thickness], center=true);
\r
293 translate([0,0,top_pixel_location_z])
\r
294 cube([top_pixel_size_x, top_pixel_size_y,epsilon_thickness], center=true);
\r
300 /* ************************************************************************/
\r
301 module extrude_character(font_index, direction_angle_x, direction_angle_y, pixel_wall_angle_x, pixel_wall_angle_y) {
\r
302 /* Extrude a (pixelated) character in a given direction:
\r
304 font_index: the index of the character in the font array
\r
305 direction_angle_x: extrusion angle (from the normal to the pixel) in the x direction
\r
306 direction_angle_y: extrusion angle (from the normal to the pixel) in the y direction
\r
307 Return a (positive) solid that can then be substracted from another solid
\r
308 (Origin at the center of the base character)
\r
310 for (tx=[0:(font_nb_pixel_x-1)]){
\r
311 for (ty=[0:(font_nb_pixel_y-1)]){
\r
312 if(FLAG_mirror_x_characters==0) { // Note: y is the 2nd coordinate, x is the 3rd (see definition of the Font)
\r
313 if(font_char[font_index][ty][tx]==1) {
\r
314 translate([(tx-(font_nb_pixel_x-1)/2)*pixel_pitch_x, (ty-(font_nb_pixel_y-1)/2)*pixel_pitch_y,0]){
\r
315 extrude_pixel(direction_angle_x,direction_angle_y, pixel_wall_angle_x, pixel_wall_angle_y);
\r
319 else { // mirror the characters across x
\r
320 if(font_char[font_index][ty][font_nb_pixel_x-1-tx]==1) {
\r
321 translate([(tx-(font_nb_pixel_x-1)/2)*pixel_pitch_x, (ty-(font_nb_pixel_y-1)/2)*pixel_pitch_y,0]){
\r
322 extrude_pixel(direction_angle_x,direction_angle_y, pixel_wall_angle_x, pixel_wall_angle_y);
\r
331 /* ************************************************************************/
\r
332 module build_create_pixel_grid(pixel_depth, ID_column_OFF=[]) {
\r
333 /* Create a grid where each intersection row/column is a potential pixel
\r
335 pixel_depth: the depth of the pixel grid
\r
336 ID_column_OFF: list all the columns that should be left OFF (eg not built), exemple: [0,1]
\r
337 Return a (positive) solid that can then be substracted from another solid
\r
338 (Origin at the center of the base character)
\r
340 if (len(ID_column_OFF)<font_nb_pixel_x) {
\r
342 cube([(font_nb_pixel_x+1)*pixel_pitch_x,(font_nb_pixel_y)*pixel_pitch_y,pixel_depth*3], center=true); // the column imprint only goes from the bottom to the top row
\r
343 // Draw the columns
\r
345 for (tx=[0:(font_nb_pixel_x-1)]){
\r
346 FLAG_draw_this_column = len( search(tx, ID_column_OFF) ) == 0;
\r
347 if (FLAG_draw_this_column ){
\r
348 translate([(tx-(font_nb_pixel_x-1)/2)*pixel_pitch_x, 0,pixel_depth/2])
\r
349 // cube([pixel_size_x,gnomon_radius*3,pixel_depth+epsilon_thickness], center=true);
\r
350 cube([0.1,gnomon_radius*3,pixel_depth], center=true);
\r
358 for (ty=[0:(font_nb_pixel_y-1)]){
\r
359 translate([0, (ty-(font_nb_pixel_y-1)/2)*pixel_pitch_y,pixel_depth/2])
\r
360 // cube([gnomon_radius*30,1.5*pixel_size_y,pixel_depth+epsilon_thickness], center=true);
\r
361 cube([gnomon_radius*30,0.1,pixel_depth], center=true);
\r
366 /* ************************************************************************/
\r
367 module build_block(gnomon_thickness, char_list, char_angle_x, char_angle_y, pixel_wall_angle_x, pixel_wall_angle_y) {
\r
368 /* Build a block with a set of characters */
\r
370 // Build The gnomon shape
\r
372 translate([0,0,gnomon_radius/2])
\r
373 cube([gnomon_thickness,2*gnomon_radius,gnomon_radius], center=true);
\r
375 rotate([90,0,90]) cylinder(r=gnomon_radius, h=gnomon_thickness, center=true, $fn=100);
\r
378 // Carve the light guides for each number
\r
379 for (ti = [0:(len(char_list)-1)]){
\r
380 extrude_character(char_list[ti],char_angle_x[ti],char_angle_y[ti], pixel_wall_angle_x, pixel_wall_angle_y);
\r
384 if (FLAG_gnomon_brim == 1) {
\r
387 cube([gnomon_thickness, gnomon_radius*2+gnomon_brim_width*2, gnomon_brim_thickness],center=true);
\r
388 cube([10*gnomon_thickness, gnomon_radius*2+gnomon_brim_gap*2, 10*gnomon_brim_thickness],center=true);
\r
393 /* ************************************************************************/
\r
394 module build_spacer_block(gnomon_thickness) {
\r
395 /* Build a spacer block*/
\r
398 // The gnomon shape
\r
400 translate([0,0,gnomon_radius/2])
\r
401 cube([gnomon_thickness+epsilon_thickness,2*gnomon_radius,gnomon_radius], center=true);
\r
403 rotate([90,0,90]) cylinder(r=gnomon_radius, h=gnomon_thickness+epsilon_thickness, center=true, $fn=100);
\r
406 build_create_pixel_grid(grid_pixel_depth, ID_column_OFF=[0,1,2,3,4]);
\r
410 if (FLAG_gnomon_brim == 1) {
\r
413 cube([gnomon_thickness, gnomon_radius*2+gnomon_brim_width*2, gnomon_brim_thickness],center=true);
\r
414 cube([10*gnomon_thickness, gnomon_radius*2+gnomon_brim_gap*2, 10*gnomon_brim_thickness],center=true);
\r
421 /* ************************************************************************/
\r
422 module build_round_top_block() {
\r
423 gnomon_thickness = gnomon_radius;
\r
424 /* Build a round top block*/
\r
427 translate([0,0,gnomon_radius/2])
\r
428 cube([gnomon_thickness,2*gnomon_radius,gnomon_radius], center=true);
\r
429 translate([gnomon_radius/2,0,0])
\r
430 scale([0.3,1,1]) sphere(r=gnomon_radius, center=true, $fn=100);
\r
435 if (FLAG_gnomon_brim == 1) {
\r
438 translate([0.35*gnomon_thickness-gnomon_brim_width/2,0,0]) cube([0.3*gnomon_thickness+gnomon_brim_width, gnomon_radius*2+gnomon_brim_width*2, gnomon_brim_thickness],center=true);
\r
439 translate([gnomon_radius/2,0,0])
\r
441 scale([0.3,1,1]) sphere(r=gnomon_radius, center=true, $fn=100);
\r
442 sphere(r=gnomon_brim_gap, center=true, $fn=10);
\r
448 /* ************************************************************************/
\r
449 module Block_hours_tens() {
\r
451 gnomon_thickness = gnomon_radius*45.0/40.0; //45;
\r
452 pixel_wall_angle_x = 0; // [degrees] angle of the walls along the x direction
\r
453 pixel_wall_angle_y = 6.0; // [degrees] angle of the walls along the y direction
\r
455 /* char_angle_x = [0,0,0,0,0,0,0];
\r
456 char_angle_y = [-45,-30,-15,0,15,30,45];
\r
457 char_list = [1,1,1,1,1,1,1];
\r
459 // Modified by Margu
\r
460 // We add intermediate angles (-37, -22, -15, -8, 8, 15, 22, 37) to display transition characters thus removing not needed material.
\r
461 // Because there is no need to make a dark transition for pixels which remain lit
\r
462 char_angle_x = [0,0,0,0,0,0,0,0,0,0,0,0,0];
\r
463 char_angle_y = [ -45,-37, -30, -22, -15, -8, 0, 8, 15, 22, 30, 38, 45];
\r
464 char_list = [1,1,1,1,1,1,1,1,1,1,1,1,1];
\r
466 build_block(gnomon_thickness, char_list, char_angle_x, char_angle_y, pixel_wall_angle_x, pixel_wall_angle_y);
\r
467 build_create_pixel_grid(grid_pixel_depth, ID_column_OFF=[]);
\r
471 /* ************************************************************************/
\r
472 module Block_hours_units() {
\r
474 gnomon_thickness = gnomon_radius*45.0/40.0; //45;
\r
475 pixel_wall_angle_x = 0; // [degrees] angle of the walls along the x direction
\r
476 pixel_wall_angle_y = 6.0; // [degrees] angle of the walls along the y direction
\r
478 // Modified by Margu
\r
479 // We add intermediate angles (-37, -22, -15, -8, 8, 15, 22, 37) to display transition characters thus removing not needed material.
\r
480 // Because there is no need to make a dark transition for pixels which remain lit
\r
481 char_angle_x = [0,0,0,0,0,0,0,0,0,0,0,0,0];
\r
482 char_angle_y = [-45,-38,-30, -22, -15,-8,0,8,15,22,30,38,45];
\r
483 char_list = [0,13,1,14,2,15,3,16,4,17,5,18,6];
\r
486 build_block(gnomon_thickness, char_list, char_angle_x, char_angle_y, pixel_wall_angle_x, pixel_wall_angle_y);
\r
487 build_create_pixel_grid(grid_pixel_depth, ID_column_OFF=[]);
\r
491 /* ************************************************************************/
\r
492 module Block_minutes_tens() {
\r
494 gnomon_thickness = gnomon_radius*45.0/40.0; //45;
\r
495 pixel_wall_angle_x = 0; // [degrees] angle of the walls along the x direction
\r
496 pixel_wall_angle_y = 1.0; // [degrees] angle of the walls along the y direction
\r
498 // Modified by Margu
\r
499 // We add intermediate angles (-48, -43, -38, -22, -15, -8, 8, 15, 22, 38, 43, 48) to display transition characters thus removing not needed material.
\r
500 // Because there is no need to make a dark transition for pixels which remain lit
\r
501 char_angle_x = [0,0,0,0,0,0, 0,0,0,0,0,0, 0,0,0,0,0,0, 0,0,0,0,0,0, 0,0,0,0,0,0, 0,0,0,0,0,0, 0];
\r
502 char_angle_y = [-50,-48,-45,-43,-40,-38, -35,-33,-30,-28,-25,-23, -20,-18,-15,-13,-10,-8, -5,-3,0,3,5,8, 10,13,15,18,20,23, 25,28,30,33,35,38, 40];
\r
503 char_list = [0,23,2,24,4,25,0,23,2,24,4,25,0,23,2,24,4,25,0,23,2,24,4,25,0,23,2,24,4,25,0,23,2,24,4,25, 0];
\r
506 build_block(gnomon_thickness, char_list, char_angle_x, char_angle_y, pixel_wall_angle_x, pixel_wall_angle_y);
\r
507 build_create_pixel_grid(grid_pixel_depth, ID_column_OFF=[]);
\r
511 /* ************************************************************************/
\r
512 module Block_minutes_units() {
\r
514 gnomon_thickness = gnomon_radius*45.0/40.0; //45;
\r
515 pixel_wall_angle_x = 0; // [degrees] angle of the walls along the x direction
\r
516 pixel_wall_angle_y = 8.0; // [degrees] angle of the walls along the y direction
\r
519 char_angle_x = [0,0,0,0,0,0,0];
\r
520 char_angle_y = [-45,-30,-15,0,15,30,45];
\r
521 char_list = [0,0,0,0,0,0,0];
\r
524 build_block(gnomon_thickness, char_list, char_angle_x, char_angle_y, pixel_wall_angle_x, pixel_wall_angle_y);
\r
525 build_create_pixel_grid(grid_pixel_depth, ID_column_OFF=[]);
\r
529 /* ************************************************************************/
\r
530 module Block_semicolon() {
\r
532 gnomon_thickness = gnomon_radius*25.0/40.0; //25;
\r
533 pixel_wall_angle_x = 0; // [degrees] angle of the walls along the x direction
\r
534 pixel_wall_angle_y = 8.0; // [degrees] angle of the walls along the y direction
\r
537 char_angle_x = [0,0,0,0,0,0,0];
\r
538 char_angle_y = [-45,-30,-15,0,15,30,45];
\r
539 char_list = [10,10,10,10,10,10,10];
\r
542 build_block(gnomon_thickness, char_list, char_angle_x, char_angle_y, pixel_wall_angle_x, pixel_wall_angle_y);
\r
543 build_create_pixel_grid(grid_pixel_depth, ID_column_OFF=[3]);
\r
547 /* ************************************************************************/
\r
548 module Block_rotating_base_upper() {
\r
549 /* Build the upper part of the rotating base */
\r
550 gnomon_thickness = gnomon_radius;
\r
551 Screw_hole_diameter = 6.5;
\r
552 Nut_width_blocking = 8.8+1.3;
\r
553 Nut_width_non_blocking = 11.2;
\r
554 Washer_Diameter = 11.9;
\r
555 Washer_thickness = 1.3;
\r
558 // Build The gnomon shape
\r
561 translate([0,0,gnomon_radius/2])
\r
562 cube([2/3*gnomon_thickness,2*gnomon_radius,gnomon_radius], center=true);
\r
564 rotate([90,0,90]) cylinder(r=gnomon_radius, h=gnomon_thickness, center=true, $fn=100);
\r
567 // The negative space for the screw, nut and washer
\r
568 translate([0,0,Washer_Diameter/2+3])
\r
569 rotate([90,0,90]) cylinder(r=Screw_hole_diameter/2, h=2*gnomon_thickness, center=true, $fn=100);
\r
570 translate([gnomon_thickness*(0.45-1/3),0,Washer_Diameter/2+3])
\r
571 rotate([90,0,90]) cylinder(r=Washer_Diameter/2+4, h=Washer_thickness+2, center=true, $fn=100);
\r
572 translate([gnomon_thickness*(0.45-1/3),0,0])
\r
573 cube([Washer_thickness+2,Washer_Diameter+8, 2*(Washer_Diameter/2+3)], center=true);
\r
574 translate([gnomon_thickness*(0.4-2/3),0,0])
\r
575 cube([gnomon_thickness*0.8+1,Nut_width_blocking, 2*(Washer_Diameter/2+3)], center=true);
\r
577 translate([gnomon_thickness*(0.45-2/3),0,Washer_Diameter/2+3])
\r
578 cube([gnomon_thickness, 2*(Nut_width_non_blocking/2+1), 2*(Nut_width_non_blocking/2+1)],center=true);
\r
579 translate([gnomon_thickness*(0.45-2/3),0,Washer_Diameter/2+3-epsilon_thickness])
\r
580 cube([gnomon_thickness*2/3+1,Nut_width_blocking, gnomon_radius], center=true);
\r
582 translate([gnomon_thickness*(0.45-2/3),0,0])
\r
583 cube([gnomon_thickness*2/3+1,Nut_width_blocking+1, 1], center=true);
\r
588 if (FLAG_gnomon_brim == 1) {
\r
591 translate([gnomon_brim_width/2,0,0,]) cube([2/3*gnomon_thickness+gnomon_brim_width, gnomon_radius*2+gnomon_brim_width*2, gnomon_brim_thickness],center=true);
\r
592 translate([-2/3*gnomon_thickness/2,0,0,]) cube([2*2/3*gnomon_thickness+gnomon_brim_gap*2, gnomon_radius*2+gnomon_brim_gap*2, 10*gnomon_brim_thickness],center=true);
\r
597 /* ************************************************************************/
\r
598 module Block_rotating_base_mid() {
\r
599 /* Build the mid part of the rotating base */
\r
600 gnomon_thickness = 1.3*gnomon_radius;
\r
601 Screw_hole_diameter = 6.5;
\r
602 Nut_width_blocking = 8.8;
\r
603 Nut_width_non_blocking = 11.2;
\r
604 Washer_Diameter = 11.9;
\r
605 Washer_thickness = 1.3;
\r
608 // The connection to the gnomon
\r
611 // The gnomon shape
\r
613 translate([0,0,gnomon_radius/2])
\r
614 cube([gnomon_thickness,2*gnomon_radius,gnomon_radius], center=true);
\r
616 rotate([90,0,90]) cylinder(r=gnomon_radius, h=gnomon_thickness, center=true, $fn=100);
\r
618 // The connection to the base
\r
620 translate([gnomon_thickness*(1-(1-0.7)/2.0),0,gnomon_radius/2])
\r
621 cube([gnomon_thickness*0.7, 0.8*gnomon_radius, gnomon_radius], center=true);
\r
622 translate([gnomon_thickness/2.0+gnomon_radius,0,0])
\r
623 rotate([90,0,90]) cylinder(r=gnomon_radius, h=2*gnomon_thickness, center=true, $fn=100);
\r
627 // The negative space for the screw and washer
\r
628 translate([0,0,Washer_Diameter/2+3])
\r
629 rotate([90,0,90]) cylinder(r=Screw_hole_diameter/2, h=20*gnomon_thickness, center=true, $fn=100);
\r
630 translate([gnomon_thickness*(0.5-4/8),0,Washer_Diameter/2+2.5])
\r
631 cube([gnomon_thickness*(6/8), 2*(Washer_Diameter/2+2), 2*(Washer_Diameter/2+3)],center=true);
\r
632 translate([gnomon_thickness*(0.5-4/8),0,Washer_Diameter+4])
\r
633 rotate([90,0,0]) scale([0.37,0.2,1]) cylinder(r=gnomon_thickness, h=2*(Washer_Diameter/2+2), center=true, $fn=100);
\r
634 translate([gnomon_thickness,0,gnomon_radius/2.0])
\r
635 rotate([90,0,0]) cylinder(r=Screw_hole_diameter/2, h=2*gnomon_thickness, center=true, $fn=100);
\r
636 /* // Small cut to reduce warping issues
\r
637 translate([gnomon_thickness,0,gnomon_radius])
\r
638 cube([1,2*gnomon_thickness,gnomon_radius], center=true);
\r
648 /* ************************************************************************/
\r
649 module Block_jar_lid_top() {
\r
650 gnomon_thickness = 2*gnomon_radius;
\r
651 Screw_hole_diameter = 6.5;
\r
652 Nut_width_blocking = 8.8;
\r
653 Nut_width_non_blocking = 11.2;
\r
654 Washer_Diameter = 11.9;
\r
655 Washer_thickness = 1.3;
\r
656 Base_Wall_thickness = 3.0;
\r
657 box_width = gnomon_radius*4;
\r
658 box_length = gnomon_radius*4;
\r
659 box_height = gnomon_radius*2;
\r
660 Base_diameter = 70;
\r
661 Connector_x_offset = 10+5;
\r
667 translate([0,0,gnomon_radius/2.0])
\r
668 rotate([90,0,0]) cylinder(r=gnomon_radius/2.0*1.2, h=gnomon_thickness*0.65, center=true, $fn=100);
\r
669 translate([Connector_x_offset,0,-0.75*gnomon_radius/2.0-Base_Wall_thickness/2]) rotate([0,0,0]) cylinder(r=Base_diameter/2 ,h=Base_Wall_thickness, center=true, $fn=100);
\r
671 // Space to rotate the gnomon
\r
672 translate([0,0,gnomon_radius/2.0])
\r
673 rotate([90,0,0]) cylinder(r=gnomon_radius*0.7, h=0.8*gnomon_radius+2*epsilon_thickness, center=true, $fn=100);
\r
674 translate([-gnomon_thickness*10,0,9.94*gnomon_radius])
\r
675 cube([gnomon_thickness*20, 0.8*gnomon_radius+2*epsilon_thickness, 20*gnomon_radius], center=true);
\r
676 translate([-gnomon_thickness*10,0,-0.06*gnomon_radius])
\r
677 rotate([0,90,0]) scale([0.3,1,1]) cylinder(r=0.4*gnomon_radius, h=gnomon_thickness*20, center=true, $fn=100);
\r
678 translate([gnomon_thickness*10,0,0.65*gnomon_radius])
\r
679 rotate([0,90,0]) scale([1.5,1,1]) cylinder(r=0.4*gnomon_radius, h=gnomon_thickness*20, center=true, $fn=100);
\r
680 // Hole for the top screw
\r
681 translate([0,0,gnomon_radius/2.0])
\r
682 rotate([90,0,0]) cylinder(r=Screw_hole_diameter/2, h=2*gnomon_thickness, center=true, $fn=100);
\r
683 // Flat surface for the top screw & washer/nut
\r
684 translate([0,-gnomon_thickness*(1+0.5/2+0.25/2-0.01)+2,gnomon_radius/2.0])
\r
685 rotate([90,0,0]) cylinder(r=1.5*Washer_Diameter/2, h=2*gnomon_thickness, center=true, $fn=100);
\r
686 translate([0,gnomon_thickness*(1+0.5/2+0.25/2-0.01)-2,gnomon_radius/2.0])
\r
687 rotate([90,0,0]) cylinder(r=1.5*Washer_Diameter/2, h=2*gnomon_thickness, center=true, $fn=100);
\r
688 // Holes for the two bottom screws
\r
689 translate([Connector_x_offset+1.1*Base_diameter/6,0,gnomon_radius/2.0])
\r
690 rotate([0,0,0]) cylinder(r=Screw_hole_diameter/2, h=2*gnomon_thickness, center=true, $fn=100);
\r
691 translate([Connector_x_offset-1.1*Base_diameter/6,0,gnomon_radius/2.0])
\r
692 rotate([0,0,0]) cylinder(r=Screw_hole_diameter/2, h=2*gnomon_thickness, center=true, $fn=100);
\r
693 // Flat surfaces for the two bottom screws
\r
694 translate([Connector_x_offset+1.1*Base_diameter/6,0,gnomon_radius*1.63-Base_Wall_thickness+Base_Wall_thickness])
\r
695 rotate([0,0,0]) cylinder(r=1.5*Washer_Diameter/2, h=2*gnomon_thickness, center=true, $fn=100);
\r
696 translate([Connector_x_offset-1.1*Base_diameter/6,0,gnomon_radius*1.63-Base_Wall_thickness+Base_Wall_thickness])
\r
697 rotate([0,0,0]) cylinder(r=1.5*Washer_Diameter/2, h=2*gnomon_thickness, center=true, $fn=100);
\r
703 /* ************************************************************************/
\r
704 module Block_jar_lid_bottom_old() {
\r
705 //Dimensions for a Bonne Maman jam jar
\r
706 Lid_diameter_outside = 88;
\r
707 Lid_diameter_inside = 82;
\r
708 Lid_thickness = 3.0;
\r
709 Lid_skirt_height_under_teeth = 0;
\r
710 Lid_skirt_full_height = 15 +Lid_thickness +Lid_skirt_height_under_teeth;
\r
711 Teeth_thickness = 2.0;
\r
713 Teeth_length = 10.0;
\r
714 Connector_x_offset = 10;
\r
715 Base_diameter = 70;
\r
716 gnomon_thickness = 2*gnomon_radius;
\r
717 Screw_hole_diameter = 6.5;
\r
719 translate([Connector_x_offset, 0,0]) {
\r
720 //The skirt of the lid
\r
722 translate([0,0,-Lid_skirt_full_height/2]) rotate([0,0,0]) cylinder(r=Lid_diameter_outside/2 ,h=Lid_skirt_full_height, center=true, $fn=100);
\r
723 translate([0,0,-Lid_skirt_full_height/2]) rotate([0,0,0]) cylinder(r=Lid_diameter_inside/2 ,h=2*Lid_skirt_full_height, center=true, $fn=100);
\r
726 translate([0,0,-Lid_skirt_full_height+Teeth_thickness/2+Lid_skirt_height_under_teeth]) intersection(){
\r
728 rotate([0,0,0]) cylinder(r=(0.5*Lid_diameter_inside+0.5*Lid_diameter_outside)/2 ,h=Teeth_thickness, center=true, $fn=100);
\r
729 rotate([0,0,0]) cylinder(r=Lid_diameter_inside/2-Teeth_depth ,h=2*Teeth_thickness, center=true, $fn=100);
\r
732 rotate([0,0,0]) cube([2*Lid_diameter_outside,Teeth_length,2*Teeth_thickness], center=true);
\r
733 rotate([0,0,60]) cube([2*Lid_diameter_outside,Teeth_length,2*Teeth_thickness], center=true);
\r
734 rotate([0,0,120]) cube([2*Lid_diameter_outside,Teeth_length,2*Teeth_thickness], center=true);
\r
737 //The flat part of the lid
\r
739 translate([0,0,-Lid_thickness/2]) rotate([0,0,0]) cylinder(r=Lid_diameter_outside/2 ,h=Lid_thickness, center=true, $fn=100);
\r
740 // Holes for the two screws
\r
741 translate([1.1*Base_diameter/6,0,gnomon_radius/2.0])
\r
742 rotate([0,0,0]) cylinder(r=Screw_hole_diameter/2, h=2*gnomon_thickness, center=true, $fn=100);
\r
743 translate([-1.1*Base_diameter/6,0,gnomon_radius/2.0])
\r
744 rotate([0,0,0]) cylinder(r=Screw_hole_diameter/2, h=2*gnomon_thickness, center=true, $fn=100);
\r
750 /* ************************************************************************/
\r
751 module Block_jar_lid_bottom() {
\r
752 //Dimensions for a Bonne Maman jam jar
\r
753 Lid_diameter_outside = 88;
\r
754 Lid_diameter_inside = 82;
\r
755 Lid_thickness = 3.0;
\r
756 Lid_skirt_height_under_teeth = 0;
\r
757 Lid_skirt_full_height = 15 +Lid_thickness +Lid_skirt_height_under_teeth;
\r
758 Teeth_thickness = 2.0;
\r
760 Teeth_length = 10.0;
\r
761 Connector_x_offset = 10;
\r
762 Base_diameter = 70;
\r
763 gnomon_thickness = 2*gnomon_radius;
\r
764 Screw_hole_diameter = 6.5;
\r
765 Logo_font_size = 6;
\r
766 Logo_negative_depth = 2;
\r
767 Logo_positive_depth = 2;
\r
768 Logo_inside_cylinder_depth = 0;
\r
769 Support_horizontal_gap = 0.2;
\r
770 Support_vertical_gap = 0.1; // should 1 layer thickness
\r
771 Support_thickness = 1.2;
\r
772 Support_height_above = 5; // for an easier removal
\r
774 translate([Connector_x_offset, 0,0]) {
\r
775 //The skirt of the lid
\r
778 //Outside shape for the skirt
\r
780 translate([0,0,-Lid_skirt_full_height+1/2]) rotate([0,0,0]) cylinder(r=Lid_diameter_outside/2*1.035 ,h=1, center=true, $fn=12); // factor 1.035 because it has 12 faces: Lid_diameter_outside/2 is the minimum distance, instead of the maximum distance
\r
781 translate([0,0,-Lid_thickness-1/2]) rotate([0,0,0]) cylinder(r=Lid_diameter_outside/2 ,h=1, center=true, $fn=100);
\r
783 // Add the MOJOPTIX Logo (positive shape)
\r
784 rotate([0,0,90]) translate([0,-Lid_diameter_outside/2+Logo_negative_depth+20,-Lid_skirt_full_height/2]) rotate([90,0,0]) linear_extrude(20) text("MOJOPTIX",size=Logo_font_size,halign="center", valign="center",font="Comic Sans MS:style=Bold");
\r
785 rotate([0,0,-30]) translate([0,-Lid_diameter_outside/2+Logo_negative_depth+20,-Lid_skirt_full_height/2]) rotate([90,0,0]) linear_extrude(20) text("MOJOPTIX",size=Logo_font_size,halign="center", valign="center",font="Comic Sans MS:style=Bold");
\r
786 rotate([0,0,210]) translate([0,-Lid_diameter_outside/2+Logo_negative_depth+20,-Lid_skirt_full_height/2]) rotate([90,0,0]) linear_extrude(20) text("MOJOPTIX",size=Logo_font_size,halign="center", valign="center",font="Comic Sans MS:style=Bold");
\r
788 //Trim the Positive shape of the MOJOPTIX Logo with a tube
\r
790 cylinder(r=10*Lid_diameter_outside/2+Logo_positive_depth,h=1000,center=true, $fn=100);
\r
791 cylinder(r=Lid_diameter_outside/2+Logo_positive_depth,h=1000,center=true, $fn=100);
\r
793 // Add the MOJOPTIX Logo (negative shape)
\r
796 rotate([0,0,90]) translate([0,-Lid_diameter_outside/2+Logo_negative_depth,-Lid_skirt_full_height/2]) rotate([90,0,0]) linear_extrude(100) text("MOJOPTIX",size=Logo_font_size,halign="center", valign="center",font="Comic Sans MS:style=Bold");
\r
797 rotate([0,0,-30]) translate([0,-Lid_diameter_outside/2+Logo_negative_depth,-Lid_skirt_full_height/2]) rotate([90,0,0]) linear_extrude(100) text("MOJOPTIX",size=Logo_font_size,halign="center", valign="center",font="Comic Sans MS:style=Bold");
\r
798 rotate([0,0,210]) translate([0,-Lid_diameter_outside/2+Logo_negative_depth,-Lid_skirt_full_height/2]) rotate([90,0,0]) linear_extrude(100) text("MOJOPTIX",size=Logo_font_size,halign="center", valign="center",font="Comic Sans MS:style=Bold");
\r
800 //Trim the Negative shape of the MOJOPTIX Logo with a cylinder
\r
801 cylinder(r=Lid_diameter_outside/2-Logo_inside_cylinder_depth,h=1000,center=true, $fn=100);
\r
803 //Inside shape for the skirt
\r
804 translate([0,0,-Lid_skirt_full_height/2]) rotate([0,0,0]) cylinder(r=Lid_diameter_inside/2 ,h=2*Lid_skirt_full_height, center=true, $fn=100);
\r
807 translate([0,0,-Lid_skirt_full_height+Teeth_thickness/2+Lid_skirt_height_under_teeth]) intersection(){
\r
809 rotate([0,0,0]) cylinder(r=(0.5*Lid_diameter_inside+0.5*Lid_diameter_outside)/2 ,h=Teeth_thickness, center=true, $fn=100);
\r
810 rotate([0,0,0]) cylinder(r=Lid_diameter_inside/2-Teeth_depth ,h=2*Teeth_thickness, center=true, $fn=100);
\r
813 rotate([0,0,0]) cube([2*Lid_diameter_outside,Teeth_length,2*Teeth_thickness], center=true);
\r
814 rotate([0,0,60]) cube([2*Lid_diameter_outside,Teeth_length,2*Teeth_thickness], center=true);
\r
815 rotate([0,0,120]) cube([2*Lid_diameter_outside,Teeth_length,2*Teeth_thickness], center=true);
\r
819 //The flat part of the lid
\r
821 translate([0,0,-Lid_thickness]) rotate_extrude(convexity = 10, $fn = 100) {
\r
822 square([Lid_diameter_outside/2-Lid_thickness,Lid_thickness], center=false);
\r
824 translate([Lid_diameter_outside/2-Lid_thickness+epsilon_thickness,0,-Lid_thickness]) scale([1,1]) circle(r=Lid_thickness, center=true);
\r
825 square([Lid_diameter_outside/2+epsilon_thickness,Lid_thickness+epsilon_thickness], center=false);
\r
828 // Holes for the two screws
\r
829 translate([1.1*Base_diameter/6,0,gnomon_radius/2.0])
\r
830 rotate([0,0,0]) cylinder(r=Screw_hole_diameter/2, h=2*gnomon_thickness, center=true, $fn=100);
\r
831 translate([-1.1*Base_diameter/6,0,gnomon_radius/2.0])
\r
832 rotate([0,0,0]) cylinder(r=Screw_hole_diameter/2, h=2*gnomon_thickness, center=true, $fn=100);
\r
833 // A single line on the 1st layer to have a custom scarring (instead of some scarring at a random place)
\r
834 translate([0,0,0]) cube([100,0.1,0.5], center=true);
\r
838 // Support structure for the teeth
\r
839 if (FLAG_bottom_lid_support == 1) {
\r
840 color("red") difference(){
\r
841 translate([0,0,-Lid_skirt_full_height/2-Lid_thickness/2-Support_vertical_gap-Support_height_above/2]) rotate([0,0,0]) cylinder(r=Lid_diameter_inside/2-Teeth_depth-Support_horizontal_gap,h=Lid_skirt_full_height-Lid_thickness+Support_height_above, center=true, $fn=100);
\r
842 translate([0,0,-Lid_skirt_full_height/2-Lid_thickness]) rotate([0,0,0]) cylinder(r=Lid_diameter_inside/2-Teeth_depth-Support_horizontal_gap-Support_thickness ,h=2*Lid_skirt_full_height+2*Support_height_above, center=true, $fn=100);
\r
843 cube([2,1000,1000],center=true);
\r
856 /* ************************************************************************/
\r
857 /* ************************************************************************/
\r
858 module Gnomon_Digits(nn) {
\r
859 /* translate([112.5/nn,0,0]) Block_hours_tens();
\r
860 translate([85/nn,0,0]) build_spacer_block(10/nn);
\r
861 translate([57.5/nn,0,0]) Block_hours_units();
\r
862 translate([30/nn,0,0]) build_spacer_block(10/nn);
\r
864 translate([12.5/nn,0,0]) Block_semicolon();
\r
866 translate([-22.5/nn,0,0]) Block_minutes_tens();
\r
867 translate([-50/nn,0,0]) build_spacer_block(10/nn);
\r
868 translate([-77.5/nn,0,0]) Block_minutes_units();
\r
870 translate([112.5/nn,0,0]) Block_hours_tens();
\r
871 translate([89/nn,0,0]) build_spacer_block(2/nn);
\r
872 translate([65.5/nn,0,0]) Block_hours_units();
\r
873 translate([38/nn,0,0]) build_spacer_block(10/nn);
\r
875 translate([20.5/nn,0,0]) Block_semicolon();
\r
877 translate([-14.5/nn,0,0]) Block_minutes_tens();
\r
878 translate([-42/nn,0,0]) build_spacer_block(10/nn);
\r
879 translate([-69.5/nn,0,0]) Block_minutes_units();
\r
883 /* ************************************************************************/
\r
884 module Gnomon_Rounded_Top(nn) {
\r
885 translate([-120/nn,0,0]) build_round_top_block();
\r
887 /* ************************************************************************/
\r
888 module Gnomon_Bottom_Connector(nn) {
\r
889 translate([155/nn,0,0]) Block_rotating_base_upper();
\r
891 /* ************************************************************************/
\r
892 module Central_Connector(nn) {
\r
893 color("red") translate([205/nn,0,0]) Block_rotating_base_mid();
\r
895 /* ************************************************************************/
\r
896 module Jar_Lid_Top(nn) {
\r
897 translate([265/nn,0,0]) Block_jar_lid_top();
\r
899 /* ************************************************************************/
\r
900 module Jar_Lid_Bottom(nn) {
\r
902 translate([265/nn,0,-24/nn]) Block_jar_lid_bottom();
\r
907 /* ************************************************************************/
\r
908 module Gnomon(nn) {
\r
910 if (FLAG_northern_hemisphere==1){
\r
911 translate([5,0,0]) Gnomon_Digits(nn);
\r
912 translate([11,0,0]) Gnomon_Rounded_Top(nn);
\r
913 translate([0,0,0]) Gnomon_Bottom_Connector(nn);
\r
916 translate([37.25,0,0]) rotate([0,0,180]) Gnomon_Digits(nn);
\r
917 translate([11,0,0]) Gnomon_Rounded_Top(nn);
\r
918 translate([0,0,0]) Gnomon_Bottom_Connector(nn);
\r
922 /* ************************************************************************/
\r
923 /* MAIN *******************************************************************/
\r
924 /* ************************************************************************/
\r
926 // Choose what you want to print/display:
\r
928 if (FLAG_PRINT == 1) Gnomon(nn);
\r
929 // 2: the central connector piece
\r
930 if (FLAG_PRINT == 2) translate([-8,0,0]) Central_Connector(nn);
\r
931 // 3: the top part of the lid
\r
932 if (FLAG_PRINT == 3) translate([-14,0,0]) Jar_Lid_Top(nn);
\r
933 // 4: the bottom part of the lid
\r
934 if (FLAG_PRINT == 4) translate([-9,0,3.75]) rotate([180,0,0]) Jar_Lid_Bottom(nn);
\r
936 if (FLAG_PRINT == 10)
\r
939 translate([-8,0,0]) Central_Connector(nn);
\r
940 translate([-14,0,0]) Jar_Lid_Top(nn);
\r
941 translate([-9,0,3.75]) Jar_Lid_Bottom(nn);
\r