Compare commits
6 Commits
6cae7dbb0e
...
98694f763b
Author | SHA1 | Date |
---|---|---|
Savanni D'Gerinel | 98694f763b | |
Savanni D'Gerinel | ce91ebc2ba | |
Savanni D'Gerinel | e44c53acf0 | |
Savanni D'Gerinel | d794b4872f | |
Savanni D'Gerinel | 8ac2cdb6ff | |
Savanni D'Gerinel | 88cf32047b |
|
@ -17,7 +17,7 @@ use rp_pico::{
|
||||||
entry,
|
entry,
|
||||||
hal::{
|
hal::{
|
||||||
clocks::init_clocks_and_plls,
|
clocks::init_clocks_and_plls,
|
||||||
gpio::{FunctionSio, Pin, PinId, PullUp, SioInput},
|
gpio::{FunctionSio, Pin, PinId, PullDown, PullUp, SioInput, SioOutput},
|
||||||
pac::{CorePeripherals, Peripherals},
|
pac::{CorePeripherals, Peripherals},
|
||||||
spi::{Enabled, Spi, SpiDevice, ValidSpiPinout},
|
spi::{Enabled, Spi, SpiDevice, ValidSpiPinout},
|
||||||
watchdog::Watchdog,
|
watchdog::Watchdog,
|
||||||
|
@ -65,12 +65,16 @@ struct BikeUI<
|
||||||
RightId: PinId,
|
RightId: PinId,
|
||||||
PreviousId: PinId,
|
PreviousId: PinId,
|
||||||
NextId: PinId,
|
NextId: PinId,
|
||||||
|
BrakeId: PinId,
|
||||||
> {
|
> {
|
||||||
spi: RefCell<Spi<Enabled, D, P, 8>>,
|
spi: RefCell<Spi<Enabled, D, P, 8>>,
|
||||||
left_blinker_button: DebouncedButton<LeftId>,
|
left_blinker_button: DebouncedButton<LeftId>,
|
||||||
right_blinker_button: DebouncedButton<RightId>,
|
right_blinker_button: DebouncedButton<RightId>,
|
||||||
previous_animation_button: DebouncedButton<PreviousId>,
|
previous_animation_button: DebouncedButton<PreviousId>,
|
||||||
next_animation_button: DebouncedButton<NextId>,
|
next_animation_button: DebouncedButton<NextId>,
|
||||||
|
brake_sensor: Pin<BrakeId, FunctionSio<SioInput>, PullUp>,
|
||||||
|
|
||||||
|
brake_enabled: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<
|
impl<
|
||||||
|
@ -80,7 +84,8 @@ impl<
|
||||||
RightId: PinId,
|
RightId: PinId,
|
||||||
PreviousId: PinId,
|
PreviousId: PinId,
|
||||||
NextId: PinId,
|
NextId: PinId,
|
||||||
> BikeUI<D, P, LeftId, RightId, PreviousId, NextId>
|
BrakeId: PinId,
|
||||||
|
> BikeUI<D, P, LeftId, RightId, PreviousId, NextId, BrakeId>
|
||||||
{
|
{
|
||||||
fn new(
|
fn new(
|
||||||
spi: Spi<Enabled, D, P, 8>,
|
spi: Spi<Enabled, D, P, 8>,
|
||||||
|
@ -88,6 +93,7 @@ impl<
|
||||||
right_blinker_button: Pin<RightId, FunctionSio<SioInput>, PullUp>,
|
right_blinker_button: Pin<RightId, FunctionSio<SioInput>, PullUp>,
|
||||||
previous_animation_button: Pin<PreviousId, FunctionSio<SioInput>, PullUp>,
|
previous_animation_button: Pin<PreviousId, FunctionSio<SioInput>, PullUp>,
|
||||||
next_animation_button: Pin<NextId, FunctionSio<SioInput>, PullUp>,
|
next_animation_button: Pin<NextId, FunctionSio<SioInput>, PullUp>,
|
||||||
|
brake_sensor: Pin<BrakeId, FunctionSio<SioInput>, PullUp>,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
Self {
|
Self {
|
||||||
spi: RefCell::new(spi),
|
spi: RefCell::new(spi),
|
||||||
|
@ -95,6 +101,9 @@ impl<
|
||||||
right_blinker_button: DebouncedButton::new(right_blinker_button),
|
right_blinker_button: DebouncedButton::new(right_blinker_button),
|
||||||
previous_animation_button: DebouncedButton::new(previous_animation_button),
|
previous_animation_button: DebouncedButton::new(previous_animation_button),
|
||||||
next_animation_button: DebouncedButton::new(next_animation_button),
|
next_animation_button: DebouncedButton::new(next_animation_button),
|
||||||
|
brake_sensor,
|
||||||
|
|
||||||
|
brake_enabled: false,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -106,10 +115,17 @@ impl<
|
||||||
RightId: PinId,
|
RightId: PinId,
|
||||||
PreviousId: PinId,
|
PreviousId: PinId,
|
||||||
NextId: PinId,
|
NextId: PinId,
|
||||||
> UI for BikeUI<D, P, LeftId, RightId, PreviousId, NextId>
|
BrakeId: PinId,
|
||||||
|
> UI for BikeUI<D, P, LeftId, RightId, PreviousId, NextId, BrakeId>
|
||||||
{
|
{
|
||||||
fn check_event(&mut self, current_time: Instant) -> Option<Event> {
|
fn check_event(&mut self, current_time: Instant) -> Option<Event> {
|
||||||
if self.left_blinker_button.is_low(current_time) {
|
if self.brake_sensor.is_high().unwrap_or(true) && !self.brake_enabled {
|
||||||
|
self.brake_enabled = true;
|
||||||
|
Some(Event::Brake)
|
||||||
|
} else if self.brake_sensor.is_low().unwrap_or(false) && self.brake_enabled {
|
||||||
|
self.brake_enabled = false;
|
||||||
|
Some(Event::BrakeRelease)
|
||||||
|
} else if self.left_blinker_button.is_low(current_time) {
|
||||||
self.left_blinker_button.set_debounce(current_time);
|
self.left_blinker_button.set_debounce(current_time);
|
||||||
Some(Event::LeftBlinker)
|
Some(Event::LeftBlinker)
|
||||||
} else if self.right_blinker_button.is_low(current_time) {
|
} else if self.right_blinker_button.is_low(current_time) {
|
||||||
|
@ -197,6 +213,9 @@ fn main() -> ! {
|
||||||
let right_blinker_button = pins.gpio16.into_pull_up_input();
|
let right_blinker_button = pins.gpio16.into_pull_up_input();
|
||||||
let previous_animation_button = pins.gpio27.into_pull_up_input();
|
let previous_animation_button = pins.gpio27.into_pull_up_input();
|
||||||
let next_animation_button = pins.gpio26.into_pull_up_input();
|
let next_animation_button = pins.gpio26.into_pull_up_input();
|
||||||
|
let brake_sensor = pins.gpio18.into_pull_up_input();
|
||||||
|
|
||||||
|
let mut led_pin = pins.led.into_push_pull_output();
|
||||||
|
|
||||||
let ui = BikeUI::new(
|
let ui = BikeUI::new(
|
||||||
spi,
|
spi,
|
||||||
|
@ -204,11 +223,11 @@ fn main() -> ! {
|
||||||
right_blinker_button,
|
right_blinker_button,
|
||||||
previous_animation_button,
|
previous_animation_button,
|
||||||
next_animation_button,
|
next_animation_button,
|
||||||
|
brake_sensor,
|
||||||
);
|
);
|
||||||
|
|
||||||
let mut app = App::new(Box::new(ui));
|
let mut app = App::new(Box::new(ui));
|
||||||
|
|
||||||
let mut led_pin = pins.led.into_push_pull_output();
|
|
||||||
led_pin.set_high();
|
led_pin.set_high();
|
||||||
|
|
||||||
let mut time = Instant::default();
|
let mut time = Instant::default();
|
||||||
|
|
|
@ -0,0 +1,189 @@
|
||||||
|
$fn = 50;
|
||||||
|
threshold = 0.1;
|
||||||
|
half_threshold = threshold / 2;
|
||||||
|
bevel = 0.5;
|
||||||
|
|
||||||
|
wire_radius = 1;
|
||||||
|
|
||||||
|
wall_thickness = 2;
|
||||||
|
cutout_threshold = 1;
|
||||||
|
|
||||||
|
battery_length = 71;
|
||||||
|
battery_width = 18.75;
|
||||||
|
|
||||||
|
cell_holder_length = battery_length + wall_thickness * 2;
|
||||||
|
cell_holder_width = battery_width + wall_thickness * 2;
|
||||||
|
cell_holder_height = battery_width + wall_thickness;
|
||||||
|
|
||||||
|
battery_contact_thickness = .6;
|
||||||
|
// battery_contact_thickness = 1;
|
||||||
|
battery_contact_width = 11;
|
||||||
|
battery_contact_length = 12.8;
|
||||||
|
battery_contact_spring_height = 10.5;
|
||||||
|
battery_contact_flange_height = 1.9;
|
||||||
|
|
||||||
|
converter_width = 11.25;
|
||||||
|
converter_length = 22.25;
|
||||||
|
converter_height = 5;
|
||||||
|
|
||||||
|
|
||||||
|
module pill(length, bevel) {
|
||||||
|
hull() {
|
||||||
|
translate([0, 0, (-length / 2) + bevel]) sphere(r = bevel);
|
||||||
|
translate([0, 0, (length / 2) - bevel]) sphere(r = bevel);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
module box_face(length, width, wall_thickness, bevel) {
|
||||||
|
center_width = width - bevel * 2;
|
||||||
|
center_length = length - bevel * 2;
|
||||||
|
|
||||||
|
hull() {
|
||||||
|
translate([-center_width / 2, -center_length / 2, 0])
|
||||||
|
pill(wall_thickness, bevel);
|
||||||
|
translate([center_width / 2, -center_length / 2, 0])
|
||||||
|
pill(wall_thickness, bevel);
|
||||||
|
translate([center_width / 2, center_length / 2, 0])
|
||||||
|
pill(wall_thickness, bevel);
|
||||||
|
translate([-center_width / 2, center_length / 2, 0])
|
||||||
|
pill(wall_thickness, bevel);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
module channel(length, width, height) {
|
||||||
|
union() {
|
||||||
|
translate([0, 0, -height / 2 + wall_thickness / 2])
|
||||||
|
box_face(length, width, wall_thickness, bevel);
|
||||||
|
translate([-width / 2 + wall_thickness / 2, 0, 0]) rotate([0, 90, 0])
|
||||||
|
box_face(length, height, wall_thickness, bevel);
|
||||||
|
translate([width / 2 - wall_thickness / 2, 0, 0]) rotate([0, 90, 0])
|
||||||
|
box_face(length, height, wall_thickness, bevel);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
module box(length, width, height) {
|
||||||
|
union() {
|
||||||
|
channel(length, width, height);
|
||||||
|
|
||||||
|
translate([0, -length / 2 + wall_thickness / 2, 0]) rotate([90, 0, 0])
|
||||||
|
box_face(height, width, wall_thickness, bevel);
|
||||||
|
|
||||||
|
translate([0, length / 2 - wall_thickness / 2, 0]) rotate([90, 0, 0])
|
||||||
|
box_face(height, width, wall_thickness, bevel);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// box(20, 10, 10);
|
||||||
|
// color("blue", 0.5) cube([10, 20, 10], center = true);
|
||||||
|
|
||||||
|
module cell_cradle(width, height) {
|
||||||
|
difference() {
|
||||||
|
translate([0, 0, -height / 2]) cube([width,
|
||||||
|
wall_thickness,
|
||||||
|
height],
|
||||||
|
center = true);
|
||||||
|
color("red", 1) translate([0, 0, 0])
|
||||||
|
rotate([90, 0, 0])
|
||||||
|
cylinder(h = wall_thickness + cutout_threshold,
|
||||||
|
r = width / 2,
|
||||||
|
center = true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
module cell_box() {
|
||||||
|
union() {
|
||||||
|
channel(cell_holder_length, cell_holder_width, cell_holder_height);
|
||||||
|
translate([0, -battery_length / 6, wall_thickness]) cell_cradle(cell_holder_width, cell_holder_height / 2);
|
||||||
|
translate([0, battery_length / 6, wall_thickness]) cell_cradle(cell_holder_width, cell_holder_height / 2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
module contact_box() {
|
||||||
|
contact_thickness = battery_contact_flange_height * .75;
|
||||||
|
cutout_width = battery_contact_width * .8;
|
||||||
|
// box_thickness = contact_thickness_ + wall_thickness * 2;
|
||||||
|
// box_height = width + wall_thickness;
|
||||||
|
|
||||||
|
difference() {
|
||||||
|
box(wall_thickness * 2 + contact_thickness, cell_holder_width, cell_holder_height);
|
||||||
|
translate([0, contact_thickness, wall_thickness * 2])
|
||||||
|
cube([battery_contact_width,
|
||||||
|
wall_thickness * 2,
|
||||||
|
battery_contact_length + threshold],
|
||||||
|
center = true);
|
||||||
|
|
||||||
|
color("red", 1) translate([0,
|
||||||
|
-(wall_thickness + contact_thickness + threshold) / 2,
|
||||||
|
cell_holder_height / 2])
|
||||||
|
cube([5, wall_thickness + threshold * 2, cell_holder_height], center = true);
|
||||||
|
|
||||||
|
translate([0,
|
||||||
|
-(wall_thickness + contact_thickness + threshold) / 2 - wire_radius,
|
||||||
|
0])
|
||||||
|
rotate([0, 90, 0])
|
||||||
|
cylinder(h = cell_holder_width, r = wire_radius, center = true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
module battery_slot() {
|
||||||
|
difference() {
|
||||||
|
union() {
|
||||||
|
translate([0, -cell_holder_length / 2, 0]) contact_box();
|
||||||
|
translate([0, wall_thickness, 0]) cell_box();
|
||||||
|
translate([0, cell_holder_length / 2 + wall_thickness * 2, 0])
|
||||||
|
rotate([0, 0, 180])
|
||||||
|
contact_box();
|
||||||
|
}
|
||||||
|
translate([cell_holder_width / 2, 1, 0]) rotate([90, 0, 0]) cylinder(h = cell_holder_length + wall_thickness * 4 + battery_contact_flange_height * 2, r = wire_radius, center = true);
|
||||||
|
translate([-cell_holder_width / 2, 1, 0]) rotate([90, 0, 0]) cylinder(h = cell_holder_length + wall_thickness * 4 + battery_contact_flange_height * 2, r = wire_radius, center = true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
module converter_box() {
|
||||||
|
box_width = wall_thickness * 2 + converter_height;
|
||||||
|
difference() {
|
||||||
|
box(box_width, cell_holder_width * 2 - wall_thickness, cell_holder_height);
|
||||||
|
|
||||||
|
translate([cell_holder_width - wire_radius, 0, 0])
|
||||||
|
rotate([90, 0, 0])
|
||||||
|
cylinder(h = box_width, r = wire_radius, center = true);
|
||||||
|
translate([cell_holder_width - wire_radius * 2, 0, 0])
|
||||||
|
rotate([0, 90, 0])
|
||||||
|
cylinder(h = wall_thickness + threshold, r = wire_radius, center = true);
|
||||||
|
|
||||||
|
translate([-cell_holder_width + wire_radius, 0, 0])
|
||||||
|
rotate([90, 0, 0])
|
||||||
|
cylinder(h = box_width, r = wire_radius, center = true);
|
||||||
|
translate([-cell_holder_width + wire_radius * 2, 0, 0])
|
||||||
|
rotate([0, 90, 0])
|
||||||
|
cylinder(h = wall_thickness + threshold, r = wire_radius, center = true);
|
||||||
|
|
||||||
|
translate([0, -box_width / 2, 0])
|
||||||
|
rotate([0, 90, 0])
|
||||||
|
cylinder(h = cell_holder_width * 2 + wall_thickness, r = wire_radius, center = true);
|
||||||
|
|
||||||
|
translate([-cell_holder_width * .75, (-box_width + wall_thickness) / 2, 0])
|
||||||
|
rotate([90, 0, 0])
|
||||||
|
cylinder(h = wall_thickness * 2, r = wire_radius, center = true);
|
||||||
|
|
||||||
|
translate([cell_holder_width * .75, (-box_width + wall_thickness) / 2, 0])
|
||||||
|
rotate([90, 0, 0])
|
||||||
|
cylinder(h = wall_thickness * 2, r = wire_radius, center = true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
module battery_case() {
|
||||||
|
union() {
|
||||||
|
translate([-cell_holder_width / 2, 0, 0]) battery_slot();
|
||||||
|
translate([cell_holder_width / 2 - wall_thickness, 0, 0]) battery_slot();
|
||||||
|
color("blue", 1)
|
||||||
|
translate([-wall_thickness / 2,
|
||||||
|
cell_holder_length / 2 + wall_thickness * 2 + battery_contact_flange_height + wall_thickness * 2 + wall_thickness / 2,
|
||||||
|
0])
|
||||||
|
converter_box();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
battery_case();
|
||||||
|
|
|
@ -0,0 +1,174 @@
|
||||||
|
width = 65;
|
||||||
|
length = 75;
|
||||||
|
height = 16;
|
||||||
|
wall_thickness = 2;
|
||||||
|
guide_thickness = 1;
|
||||||
|
power_width = 21;
|
||||||
|
output_width = 37.5;
|
||||||
|
half_wall_thickness = wall_thickness / 2;
|
||||||
|
standoff_thickness = 10;
|
||||||
|
hole_diameter = 3;
|
||||||
|
// The radius of a nut in mm. However, based on my measurements, I'm not actually sure I have this right. The short height of a nut is 7.86mm. Derive from there.
|
||||||
|
nut_radius = 8.5 * cos(30) / 2;
|
||||||
|
nut_height = 2.69; // mm
|
||||||
|
screw_radius = 2;
|
||||||
|
handlebar_radius = 15;
|
||||||
|
clasp_thickness = 4;
|
||||||
|
clasp_width = 35;
|
||||||
|
circular_face_count = 96;
|
||||||
|
|
||||||
|
module hexagon(r, h) {
|
||||||
|
pi = 3.1415926;
|
||||||
|
polyhedron(
|
||||||
|
points=[
|
||||||
|
[r, 0, 0],
|
||||||
|
[r * cos(60), r * sin(60), 0],
|
||||||
|
[r * cos(120), r * sin(120), 0],
|
||||||
|
[r * cos(180), r * sin(180), 0],
|
||||||
|
[r * cos(240), r * sin(240), 0],
|
||||||
|
[r * cos(300), r * sin(300), 0],
|
||||||
|
|
||||||
|
[r, 0, h],
|
||||||
|
[r * cos(60), r * sin(60), h],
|
||||||
|
[r * cos(120), r * sin(120), h],
|
||||||
|
[r * cos(180), r * sin(180), h],
|
||||||
|
[r * cos(240), r * sin(240), h],
|
||||||
|
[r * cos(300), r * sin(300), h],
|
||||||
|
],
|
||||||
|
faces=[
|
||||||
|
[0, 1, 2, 3, 4, 5],
|
||||||
|
[11, 10, 9, 8, 7, 6],
|
||||||
|
[6, 7, 1, 0],
|
||||||
|
[7, 8, 2, 1],
|
||||||
|
[8, 9, 3, 2],
|
||||||
|
[9, 10, 4, 3],
|
||||||
|
[10, 11, 5, 4],
|
||||||
|
[11, 6, 0, 5],
|
||||||
|
]
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Nut holders are blocks that have a hole drilled through them and a hexagonal-shaped cavity. The idea is to
|
||||||
|
module nut_holder() {
|
||||||
|
difference() {
|
||||||
|
translate([-4.5, -4.5, -2]) cube([9, 9, 4]);
|
||||||
|
union() {
|
||||||
|
translate([0, 0, -1]) hexagon(nut_radius, 2);
|
||||||
|
cylinder(h = 6, r = screw_radius, center = true, $fn = 24);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
module screw_hole() {
|
||||||
|
union() {
|
||||||
|
translate([0, 0, 4]) cylinder(h = 2.1, r = screw_radius * 2, center = true, $fn = 24);
|
||||||
|
cylinder(h = 6, r = screw_radius, center = true, $fn = 24);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
module base() {
|
||||||
|
cube([width, length, wall_thickness]);
|
||||||
|
}
|
||||||
|
|
||||||
|
module face() {
|
||||||
|
union() {
|
||||||
|
cube([width, length, wall_thickness / 2]);
|
||||||
|
translate([wall_thickness, wall_thickness, wall_thickness / 2]) cube([width-wall_thickness*2, length-wall_thickness*2, wall_thickness / 2]);
|
||||||
|
translate([4.5 + wall_thickness, 4.5 + wall_thickness, 4]) nut_holder();
|
||||||
|
translate([width - 4.5 - wall_thickness, 4.5 + wall_thickness, 4]) nut_holder();
|
||||||
|
translate([width - 4.5 - wall_thickness, length - 4.5 - wall_thickness, 4]) nut_holder();
|
||||||
|
translate([4.5 + wall_thickness, length - 4.5 - wall_thickness, 4]) nut_holder();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
module wall(length) {
|
||||||
|
cube([length, height, wall_thickness]);
|
||||||
|
}
|
||||||
|
|
||||||
|
module power_wall() {
|
||||||
|
difference() {
|
||||||
|
wall(65);
|
||||||
|
translate([9, 2, -.5]) cube([power_width, height, wall_thickness + 1]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
module output_wall() {
|
||||||
|
difference() {
|
||||||
|
wall(65);
|
||||||
|
translate([9, 2, -.5]) cube([output_width, height, wall_thickness + 1]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Use hexagons as cutouts into which I can install a hex nut. This isn't quite right yet, but close.
|
||||||
|
// hexagon(nut_radius, 1);
|
||||||
|
|
||||||
|
// cube([standoff_thickness, standoff_thickness, 2]);
|
||||||
|
|
||||||
|
/*
|
||||||
|
difference() {
|
||||||
|
union() {
|
||||||
|
base();
|
||||||
|
rotate([90, 0, 90]) wall(75);
|
||||||
|
// translate([width - wall_thickness, 0, 0]) rotate([90, 0, 90]) wall(length);
|
||||||
|
// rotate([90, 0, 0]) power_wall();
|
||||||
|
// translate([0, length, 0]) rotate([90, 0, 0]) output_wall();
|
||||||
|
// translate([wall_thickness,
|
||||||
|
// wall_thickness,
|
||||||
|
// wall_thickness]) standoff();
|
||||||
|
// translate([width - wall_thickness - standoff_thickness,
|
||||||
|
// wall_thickness,
|
||||||
|
// wall_thickness]) standoff();
|
||||||
|
// translate([wall_thickness,
|
||||||
|
// length - wall_thickness - standoff_thickness,
|
||||||
|
// wall_thickness]) standoff();
|
||||||
|
// translate([width - wall_thickness - standoff_thickness,
|
||||||
|
// length - wall_thickness - standoff_thickness,
|
||||||
|
// wall_thickness]) standoff();
|
||||||
|
}
|
||||||
|
// translate([-half_wall_thickness, -wall_thickness - half_wall_thickness, height - half_wall_thickness]) cube([wall_thickness, length + wall_thickness * 2, wall_thickness]);
|
||||||
|
// translate([width - half_wall_thickness, -wall_thickness - half_wall_thickness, height - half_wall_thickness]) cube([wall_thickness, length + wall_thickness * 2, wall_thickness]);
|
||||||
|
// translate([-half_wall_thickness, -half_wall_thickness, height - half_wall_thickness]) rotate([0, 0, 270]) cube([wall_thickness, width + wall_thickness * 2, wall_thickness]);
|
||||||
|
// translate([-half_wall_thickness, length + half_wall_thickness, height - half_wall_thickness]) rotate([0, 0, 270]) cube([wall_thickness, width + wall_thickness * 2, wall_thickness]);
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
module box() {
|
||||||
|
difference() {
|
||||||
|
union() {
|
||||||
|
cube([width, length, wall_thickness * 2]);
|
||||||
|
translate([0, 0, wall_thickness]) rotate([90, 0, 90]) wall(length);
|
||||||
|
translate([width - wall_thickness, 0, wall_thickness]) rotate([90, 0, 90]) wall(length);
|
||||||
|
translate([0, wall_thickness, wall_thickness]) rotate([90, 0, 0]) wall(width);
|
||||||
|
translate([0, length, wall_thickness]) rotate([90, 0, 0]) wall(width);
|
||||||
|
}
|
||||||
|
translate([4.5 + wall_thickness, 4.5 + wall_thickness, 4]) rotate([180, 0, 0]) screw_hole();
|
||||||
|
translate([width - 4.5 - wall_thickness, 4.5 + wall_thickness, 4]) rotate([180, 0, 0]) screw_hole();
|
||||||
|
translate([width - 4.5 - wall_thickness, length - 4.5 - wall_thickness, 4]) rotate([180, 0, 0]) screw_hole();
|
||||||
|
translate([4.5 + wall_thickness, length - 4.5 - wall_thickness, 4]) rotate([180, 0, 0]) screw_hole();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
module top_clasp() {
|
||||||
|
difference() {
|
||||||
|
union() {
|
||||||
|
cylinder(h = clasp_width, r = handlebar_radius + clasp_thickness, center = true, $fn = circular_face_count);
|
||||||
|
translate([0, 0, -clasp_width / 2]) cylinder(h = 1, r = handlebar_radius + clasp_thickness + 1.5, center = true, $fn = circular_face_count);
|
||||||
|
translate([0, 0, -clasp_width / 2 + 4]) cylinder(h = 1, r = handlebar_radius + clasp_thickness + 1.5, center = true, $fn = circular_face_count);
|
||||||
|
translate([0, 0, clasp_width / 2]) cylinder(h = 1, r = handlebar_radius + clasp_thickness + 1.5, center = true, $fn = circular_face_count);
|
||||||
|
translate([0, 0, clasp_width / 2 - 4]) cylinder(h = 1, r = handlebar_radius + clasp_thickness + 1.5, center = true, $fn = circular_face_count);
|
||||||
|
translate([-handlebar_radius-5, -10, -clasp_width / 2 + 6]) cube([6, 20, clasp_width - 12]);
|
||||||
|
}
|
||||||
|
translate([-0.5, 0, 0]) cylinder(h = clasp_width+2, r = handlebar_radius + 1, center = true, $fn = circular_face_count);
|
||||||
|
translate([-0.5, -handlebar_radius - 10, -clasp_width / 2 - 1]) cube([handlebar_radius + 10, handlebar_radius * 2 + 20, clasp_width + 2]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
module body() {
|
||||||
|
union() {
|
||||||
|
box();
|
||||||
|
// translate([width / 2, length / 2, -5 - handlebar_radius]) rotate([0, 90, 90]) top_clasp();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
body();
|
||||||
|
// translate([width + 10, 0, 0]) face();
|
Loading…
Reference in New Issue