// Paràmetres globals $fn = 50; // Resolució per cercles i corbes // Paràmetres de posició solar (en graus) lat_deg = 41.5; // Latitud de Martorell delta_deg = 0; // Declinació solar (0 per equinocci) // Paràmetres del gnomó i de la projecció L = 50; // Alçada del gnomó (mm) // Paràmetres del display de 7 segments digit_width = 10; // Amplada d'un dígit (mm) digit_height = 20; // Alçada d'un dígit (mm) segment_thickness = 2; // Gruix del segment (mm) segment_length = 8; // Longitud dels segments (mm) gap_segment = 1; // Espai entre segments (mm) hole_offset = 0.5; // Offset per assegurar que el forat talla completament // Paràmetres de la peça base plate_thickness = 5; // Gruix del plat (mm) plate_size = 250; // Mida de la base (pla quadrat, mm) // Funcions per convertir graus <-> radians function toRadians(deg) = deg * PI / 180; function toDegrees(rad) = rad * 180 / PI; // Funció per "padding" d'un nombre a dos dígits (com a string) function pad(n) = (n < 10) ? str("0", n) : str(n); // Mapa dels segments per cada dígit (ordre: a, b, c, d, e, f, g) segments = [ [1,1,1,1,1,1,0], // 0 [0,1,1,0,0,0,0], // 1 [1,1,0,1,1,0,1], // 2 [1,1,1,1,0,0,1], // 3 [0,1,1,0,0,1,1], // 4 [1,0,1,1,0,1,1], // 5 [1,0,1,1,1,1,1], // 6 [1,1,1,0,0,0,0], // 7 [1,1,1,1,1,1,1], // 8 [1,1,1,1,0,1,1] // 9 ]; // Mòdul per crear un segment module segment(seg_type = "horizontal") { if (seg_type == "horizontal") { linear_extrude(height = plate_thickness + hole_offset) offset(r = hole_offset) square([segment_length, segment_thickness], center = true); } else { // vertical linear_extrude(height = plate_thickness + hole_offset) offset(r = hole_offset) square([segment_thickness, segment_length], center = true); } } // Mòdul per crear un dígit de 7 segments module seven_segment_digit(d = 0) { seg = segments[d]; // Segment "a" (horitzontal, superior) translate([0, digit_height/2 - segment_thickness/2]) if (seg[0]) segment("horizontal"); // Segment "b" (vertical, lateral dret superior) translate([digit_width/2 - segment_thickness/2, digit_height/4]) if (seg[1]) segment("vertical"); // Segment "c" (vertical, lateral dret inferior) translate([digit_width/2 - segment_thickness/2, -digit_height/4]) if (seg[2]) segment("vertical"); // Segment "d" (horitzontal, inferior) translate([0, -digit_height/2 + segment_thickness/2]) if (seg[3]) segment("horizontal"); // Segment "e" (vertical, lateral esquerre inferior) translate([-digit_width/2 + segment_thickness/2, -digit_height/4]) if (seg[4]) segment("vertical"); // Segment "f" (vertical, lateral esquerre superior) translate([-digit_width/2 + segment_thickness/2, digit_height/4]) if (seg[5]) segment("vertical"); // Segment "g" (horitzontal, central) translate([0, 0]) if (seg[6]) segment("horizontal"); } // Mòdul per crear els dos punts module colon() { translate([0, digit_height/4, 0]) cylinder(h = plate_thickness + hole_offset, r = segment_thickness/2, center = true); translate([0, -digit_height/4, 0]) cylinder(h = plate_thickness + hole_offset, r = segment_thickness/2, center = true); } // Mòdul per crear un display complet de 4 dígits amb dos punts (format HH:MM) module time_display(time_str = "0900") { digit_spacing = digit_width + gap_segment; for(i = [0 : 4]) { if (i == 2) { // Afegim els dos punts després del segon dígit translate([-0.5 * digit_spacing, 0, 0]) colon(); } else { // Extracció de cada caràcter del string ch = time_str[i < 2 ? i : i-1]; // Convertir el caràcter a nombre digit_val = ord(ch) - 48; translate([(i < 2 ? -1.75 : -1.25) * digit_spacing + i * digit_spacing, 0, 0]) seven_segment_digit(d = digit_val); } } } // Càlcul de la posició solar per cada temps module solar_display_array() { lat = toRadians(lat_deg); delta = toRadians(delta_deg); for(t = [540 : 5 : 1080]) { // t en minuts T = t / 60; // temps en hores // Càlcul de l'angle horari (ω) omega_deg = 15 * (T - 12); omega = toRadians(omega_deg); // Altura solar h h = asin(sin(lat) * sin(delta) + cos(lat) * cos(delta) * cos(omega)); // Zenith (z) z = (PI/2) - h; // Distància de projecció r r = L * tan(z); // Azimut A sinA = cos(delta) * sin(omega) / cos(h); cosA = (sin(delta) - sin(h)*sin(lat)) / (cos(h)*cos(lat)); A = atan2(sinA, cosA); // Posició de la projecció (x, y) x_offset = r * sin(A); y_offset = r * cos(A); // Format del temps en HHMM hour = floor(t/60); minutes = t % 60; time_str = str(pad(hour), pad(minutes)); // Col·loca cada display a la seva posició calculada translate([x_offset, y_offset, 0]) time_display(time_str = time_str); } } // Peça final difference() { // Peça base translate([-plate_size/2, -plate_size/2, 0]) cube([plate_size, plate_size, plate_thickness]); // Retalla els forats per cada display translate([0, 0, -0.5]) solar_display_array(); }