├── OpenSCAD ├── arduino_nano_enclosure │ ├── arduino_nano_enclosure.scad │ ├── arduino_nano_enclosure.stl │ ├── arduino_nano_enclosure_dimensions.scad │ ├── arduino_nano_enclosure_lid.scad │ └── arduino_nano_enclosure_lid.stl ├── arduino_nano_pololu_md01b_mounting_plate │ ├── arduino_nano_pololu_md01b_mounting_plate_90_center.scad │ └── arduino_nano_pololu_md01b_mounting_plate_90_center.stl ├── banebots │ └── p60.scad ├── motor_plate │ ├── motor_plate.png │ ├── motor_plate.scad │ ├── motor_plate.stl │ ├── motor_plate_dimensions.scad │ ├── motor_plate_mounting_bracket.scad │ └── motor_plate_mounting_bracket.stl ├── motor_plate_front │ ├── motor_plate_front.scad │ ├── motor_plate_front.stl │ ├── motor_plate_front_bottom.stl │ └── motor_plate_front_top.stl ├── motor_plate_side │ ├── motor_plate_side.scad │ └── motor_plate_side.stl ├── mre_gear_box │ ├── bearing_block.scad │ ├── bearing_block.stl │ ├── bearing_block_dimensions.scad │ ├── bearing_spacer.scad │ ├── bearing_spacer.stl │ ├── bearing_spacer_plate.scad │ ├── bearing_spacer_plate.stl │ ├── gear_dimensions.scad │ ├── gearbox_cover.scad │ ├── gearbox_cover.stl │ ├── gearbox_cover_dimensions.scad │ ├── mre_gear.scad │ ├── mre_gear.stl │ ├── mre_gear_plug.scad │ ├── mre_gear_plug.stl │ ├── output_shaft_gear.scad │ └── output_shaft_gear.stl ├── pololu_md01b_mounting_plate │ ├── pololu_md01b_mounting_plate.scad │ └── pololu_md01b_mounting_plate.stl └── resolution.scad ├── PololuDriver ├── PololuDriver.cpp └── PololuDriver.h ├── README.md ├── diyservo └── diyservo.ino └── docs ├── WiringMadScientistHutMRE.txt ├── WiringPololuMDB01.txt └── pololu_mdb01_pinout.jpg /OpenSCAD/arduino_nano_enclosure/arduino_nano_enclosure.scad: -------------------------------------------------------------------------------- 1 | /* Copyright 2013 CreateThis.com 2 | * All Rights Reserved 3 | */ 4 | 5 | include <../resolution.scad> 6 | include 7 | 8 | module arduino_nano_enclosure(cut_holes = true) { 9 | difference () { 10 | union() { 11 | // case 12 | difference(){ 13 | // outer 14 | cube(size = [dimension_width,dimension_length,dimension_height], center = true); 15 | 16 | // inner 17 | translate(v = [ 0,0,dimension_bottom_thickness]) { 18 | cube(size = [dimension_arduino_nano_pcb_width,dimension_arduino_nano_pcb_length,dimension_inner_height], center = true); 19 | } 20 | } 21 | 22 | // PCB supports 23 | translate(v = [0,0,-dimension_support_z]) { 24 | // top 25 | 26 | // right 27 | translate(v = [ dimension_center_to_support_right,dimension_center_to_support_top,0]) { 28 | cube(size = [dimension_arduino_nano_pcb_support_width,dimension_arduino_nano_pcb_support_width,dimension_support_height], center = true); 29 | } 30 | 31 | // left 32 | translate(v = [ -dimension_center_to_support_right,dimension_center_to_support_top,0]) { 33 | cube(size = [dimension_arduino_nano_pcb_support_width,dimension_arduino_nano_pcb_support_width,dimension_support_height], center = true); 34 | } 35 | 36 | // bottom 37 | 38 | // right 39 | translate(v = [ dimension_center_to_support_right,-dimension_center_to_support_top,0]) { 40 | cube(size = [dimension_arduino_nano_pcb_support_width,dimension_arduino_nano_pcb_support_width,dimension_support_height], center = true); 41 | } 42 | 43 | // left 44 | translate(v = [ -dimension_center_to_support_right,-dimension_center_to_support_top,0]) { 45 | cube(size = [dimension_arduino_nano_pcb_support_width,dimension_arduino_nano_pcb_support_width,dimension_support_height], center = true); 46 | } 47 | } 48 | 49 | // Mounting Hole Casings 50 | 51 | // top 52 | 53 | // right 54 | translate(v = [ dimension_center_to_screw_hole_right,dimension_center_to_screw_hole_top,0]) { 55 | // outer 56 | cylinder(h = dimension_height,r = dimension_screw_hole_outer_radius,center = true, $fn = resolution); 57 | } 58 | 59 | // left 60 | translate(v = [ -dimension_center_to_screw_hole_right,dimension_center_to_screw_hole_top,0]) { 61 | // outer 62 | cylinder(h = dimension_height,r = dimension_screw_hole_outer_radius,center = true, $fn = resolution); 63 | } 64 | 65 | // bottom 66 | 67 | // right 68 | translate(v = [ dimension_center_to_screw_hole_right,-dimension_center_to_screw_hole_top,0]) { 69 | // outer 70 | cylinder(h = dimension_height,r = dimension_screw_hole_outer_radius,center = true, $fn = resolution); 71 | } 72 | 73 | // left 74 | translate(v = [ -dimension_center_to_screw_hole_right,-dimension_center_to_screw_hole_top,0]) { 75 | // outer 76 | cylinder(h = dimension_height,r = dimension_screw_hole_outer_radius,center = true, $fn = resolution); 77 | } 78 | } 79 | 80 | if (cut_holes) { 81 | arduino_nano_enclosure_holes(); 82 | } 83 | } 84 | } 85 | 86 | module arduino_nano_enclosure_holes() { 87 | // ICSP header cutout 88 | translate(v = [ 0,dimension_center_to_icsp_header,-1]) { 89 | cube(size = [dimension_icsp_header_length,dimension_icsp_header_width,dimension_inner_height*2], center = true); 90 | } 91 | 92 | // USB header cutout 93 | translate(v = [ 0,-dimension_center_to_usb_header,dimension_usb_header_z + 0.0001 /* bug fix for OpenSCAD math */]) { 94 | cube(size = [dimension_usb_cable_width,dimension_usb_header_length,dimension_usb_cable_height], center = true); 95 | } 96 | 97 | // Mounting Holes 98 | 99 | // top 100 | 101 | // right 102 | translate(v = [ dimension_center_to_screw_hole_right,dimension_center_to_screw_hole_top,0]) { 103 | // outer 104 | cylinder(h = dimension_height*2,r = dimension_screw_hole_radius,center = true, $fn = resolution); 105 | } 106 | 107 | // left 108 | translate(v = [ -dimension_center_to_screw_hole_right,dimension_center_to_screw_hole_top,0]) { 109 | // outer 110 | cylinder(h = dimension_height*2,r = dimension_screw_hole_radius,center = true, $fn = resolution); 111 | } 112 | 113 | // bottom 114 | 115 | // right 116 | translate(v = [ dimension_center_to_screw_hole_right,-dimension_center_to_screw_hole_top,0]) { 117 | // outer 118 | cylinder(h = dimension_height*2,r = dimension_screw_hole_radius,center = true, $fn = resolution); 119 | } 120 | 121 | // left 122 | translate(v = [ -dimension_center_to_screw_hole_right,-dimension_center_to_screw_hole_top,0]) { 123 | // outer 124 | cylinder(h = dimension_height*2,r = dimension_screw_hole_radius,center = true, $fn = resolution); 125 | } 126 | } 127 | 128 | function arduino_nano_enclosure_width() = dimension_width + dimension_screw_hole_outer_radius*2; 129 | function arduino_nano_enclosure_length() = dimension_length; 130 | function arduino_nano_enclosure_height() = dimension_height; 131 | function arduino_nano_enclosure_distance_between_holes_width() = dimension_center_to_screw_hole_right * 2; 132 | 133 | arduino_nano_enclosure(); 134 | -------------------------------------------------------------------------------- /OpenSCAD/arduino_nano_enclosure/arduino_nano_enclosure_dimensions.scad: -------------------------------------------------------------------------------- 1 | include <../resolution.scad> 2 | 3 | // Case 4 | dimension_bottom_thickness = 1.10; 5 | dimension_bottom_to_board_bottom = 8.09; // includes bottom thickness 6 | dimension_wall_thickness = 3.57; 7 | dimension_screw_hole_diameter = 3.43; // This accepts a #6-32 screw 8 | dimension_screw_hole_wall_thickness = 2.17; 9 | 10 | // Lid 11 | dimension_lid_thickness = 3.57; 12 | dimension_lid_support_height = 3.10; 13 | 14 | // PCB 15 | dimension_arduino_nano_pcb_width = 17.84; 16 | dimension_arduino_nano_pcb_length = 43.24; 17 | dimension_arduino_nano_pcb_thickness = 1.66; 18 | dimension_arduino_nano_pcb_support_width = 2.56; 19 | 20 | // ICSP header 21 | dimension_icsp_header_length = 7.94; 22 | dimension_icsp_header_width = 5.0; 23 | dimension_icsp_header_height = 8.28; 24 | 25 | // Mini-B USB header 26 | dimension_usb_header_height = 3.91; 27 | dimension_usb_header_width = 7.50; 28 | dimension_usb_header_length = 9.24; // NOTE: This dimension is meaningless. I'm just using it to cut a hole. 29 | 30 | // Mini-B USB cable 31 | dimension_usb_cable_width = 10.22; 32 | dimension_usb_cable_height = 9.2; 33 | 34 | // Calculated dimensions 35 | dimension_width = dimension_arduino_nano_pcb_width + dimension_wall_thickness * 2; 36 | dimension_length = dimension_arduino_nano_pcb_length + dimension_wall_thickness * 2; 37 | dimension_height = dimension_icsp_header_height + dimension_arduino_nano_pcb_thickness; 38 | dimension_inner_height = dimension_height - dimension_bottom_thickness; 39 | dimension_support_height = dimension_icsp_header_height; 40 | dimension_support_z = (dimension_height - dimension_support_height) / 2; 41 | dimension_center_to_support_right = dimension_arduino_nano_pcb_width / 2 - dimension_arduino_nano_pcb_support_width / 2; 42 | dimension_center_to_support_top = dimension_arduino_nano_pcb_length / 2 - dimension_arduino_nano_pcb_support_width / 2; 43 | dimension_center_to_icsp_header = dimension_arduino_nano_pcb_length / 2 - dimension_icsp_header_width / 2; 44 | dimension_center_to_usb_header = dimension_arduino_nano_pcb_length / 2; 45 | dimension_bottom_to_usb_header = dimension_inner_height - dimension_usb_header_height - dimension_arduino_nano_pcb_thickness; 46 | dimension_usb_header_cutout_height = dimension_usb_header_height + dimension_arduino_nano_pcb_thickness; 47 | dimension_usb_header_z = (dimension_height - dimension_arduino_nano_pcb_thickness - dimension_usb_header_height/2 - dimension_usb_cable_height/2)/2 ; 48 | dimension_screw_hole_outer_diameter = dimension_screw_hole_diameter + dimension_screw_hole_wall_thickness * 2; 49 | dimension_screw_hole_radius = dimension_screw_hole_diameter / 2; 50 | dimension_screw_hole_outer_radius = dimension_screw_hole_outer_diameter / 2; 51 | dimension_center_to_screw_hole_right = dimension_width / 2 + dimension_screw_hole_outer_radius - dimension_wall_thickness; 52 | dimension_center_to_screw_hole_top = dimension_length / 2 - dimension_screw_hole_outer_radius; 53 | dimension_lid_support_z = (dimension_lid_thickness - dimension_lid_support_height) / 2; 54 | dimension_distance_between_supports = dimension_arduino_nano_pcb_width - dimension_arduino_nano_pcb_support_width * 2; 55 | -------------------------------------------------------------------------------- /OpenSCAD/arduino_nano_enclosure/arduino_nano_enclosure_lid.scad: -------------------------------------------------------------------------------- 1 | /* Copyright 2013 CreateThis.com 2 | * All Rights Reserved 3 | */ 4 | 5 | module arduino_nano_enclosure_lid() { 6 | include 7 | 8 | // Do it. 9 | difference () { 10 | union() { 11 | // case 12 | difference(){ 13 | // outer 14 | cube(size = [dimension_width,dimension_length,dimension_lid_thickness], center = true); 15 | 16 | // inner 17 | cube(size = [dimension_arduino_nano_pcb_width,dimension_arduino_nano_pcb_length,dimension_lid_thickness], center = true); 18 | 19 | // open front cutout 20 | translate(v = [ 0,-dimension_center_to_usb_header,0]) { 21 | cube(size = [dimension_distance_between_supports,dimension_usb_header_length,dimension_usb_header_cutout_height], center = true); 22 | } 23 | } 24 | 25 | // PCB supports 26 | translate(v = [0,0,-dimension_lid_support_z]) { 27 | // top 28 | 29 | // right 30 | translate(v = [ dimension_center_to_support_right,dimension_center_to_support_top,0]) { 31 | cube(size = [dimension_arduino_nano_pcb_support_width,dimension_arduino_nano_pcb_support_width,dimension_lid_support_height], center = true); 32 | } 33 | 34 | // left 35 | translate(v = [ -dimension_center_to_support_right,dimension_center_to_support_top,0]) { 36 | cube(size = [dimension_arduino_nano_pcb_support_width,dimension_arduino_nano_pcb_support_width,dimension_lid_support_height], center = true); 37 | } 38 | 39 | // bottom 40 | 41 | // right 42 | translate(v = [ dimension_center_to_support_right,-dimension_center_to_support_top,0]) { 43 | cube(size = [dimension_arduino_nano_pcb_support_width,dimension_arduino_nano_pcb_support_width,dimension_lid_support_height], center = true); 44 | } 45 | 46 | // left 47 | translate(v = [ -dimension_center_to_support_right,-dimension_center_to_support_top,0]) { 48 | cube(size = [dimension_arduino_nano_pcb_support_width,dimension_arduino_nano_pcb_support_width,dimension_lid_support_height], center = true); 49 | } 50 | } 51 | 52 | // Mounting Hole Casings 53 | 54 | // top 55 | 56 | // right 57 | translate(v = [ dimension_center_to_screw_hole_right,dimension_center_to_screw_hole_top,0]) { 58 | // outer 59 | cylinder(h = dimension_lid_thickness,r = dimension_screw_hole_outer_radius,center = true, $fn = resolution); 60 | } 61 | 62 | // left 63 | translate(v = [ -dimension_center_to_screw_hole_right,dimension_center_to_screw_hole_top,0]) { 64 | // outer 65 | cylinder(h = dimension_lid_thickness,r = dimension_screw_hole_outer_radius,center = true, $fn = resolution); 66 | } 67 | 68 | // bottom 69 | 70 | // right 71 | translate(v = [ dimension_center_to_screw_hole_right,-dimension_center_to_screw_hole_top,0]) { 72 | // outer 73 | cylinder(h = dimension_lid_thickness,r = dimension_screw_hole_outer_radius,center = true, $fn = resolution); 74 | } 75 | 76 | // left 77 | translate(v = [ -dimension_center_to_screw_hole_right,-dimension_center_to_screw_hole_top,0]) { 78 | // outer 79 | cylinder(h = dimension_lid_thickness,r = dimension_screw_hole_outer_radius,center = true, $fn = resolution); 80 | } 81 | } 82 | 83 | // Mounting Holes 84 | 85 | // top 86 | 87 | // right 88 | translate(v = [ dimension_center_to_screw_hole_right,dimension_center_to_screw_hole_top,0]) { 89 | // outer 90 | cylinder(h = dimension_lid_thickness,r = dimension_screw_hole_radius,center = true, $fn = resolution); 91 | } 92 | 93 | // left 94 | translate(v = [ -dimension_center_to_screw_hole_right,dimension_center_to_screw_hole_top,0]) { 95 | // outer 96 | cylinder(h = dimension_lid_thickness,r = dimension_screw_hole_radius,center = true, $fn = resolution); 97 | } 98 | 99 | // bottom 100 | 101 | // right 102 | translate(v = [ dimension_center_to_screw_hole_right,-dimension_center_to_screw_hole_top,0]) { 103 | // outer 104 | cylinder(h = dimension_lid_thickness,r = dimension_screw_hole_radius,center = true, $fn = resolution); 105 | } 106 | 107 | // left 108 | translate(v = [ -dimension_center_to_screw_hole_right,-dimension_center_to_screw_hole_top,0]) { 109 | // outer 110 | cylinder(h = dimension_lid_thickness,r = dimension_screw_hole_radius,center = true, $fn = resolution); 111 | } 112 | } 113 | } 114 | 115 | arduino_nano_enclosure_lid(); 116 | -------------------------------------------------------------------------------- /OpenSCAD/arduino_nano_pololu_md01b_mounting_plate/arduino_nano_pololu_md01b_mounting_plate_90_center.scad: -------------------------------------------------------------------------------- 1 | /* Copyright 2013 CreateThis.com 2 | * All Rights Reserved 3 | */ 4 | 5 | include <../resolution.scad> 6 | use <../arduino_nano_enclosure/arduino_nano_enclosure.scad> 7 | use <../pololu_md01b_mounting_plate/pololu_md01b_mounting_plate.scad> 8 | 9 | // Calculated dimensions 10 | dimension_bottom_thickness = pololu_md01b_mounting_plate_bottom_thickness()*2; 11 | dimension_width = arduino_nano_enclosure_width() + pololu_md01b_mounting_plate_width(); 12 | dimension_length = arduino_nano_enclosure_length(); 13 | arduino_nano_x = -dimension_width/2+arduino_nano_enclosure_width()/2; 14 | arduino_nano_z = arduino_nano_enclosure_height()/2; 15 | pololu_md01b_x = -dimension_width/2 + arduino_nano_enclosure_width() + pololu_md01b_mounting_plate_width()/2; 16 | pololu_md01b_y = 0; 17 | pololu_md01b_z = dimension_bottom_thickness/4; 18 | 19 | 20 | difference() { 21 | union() { 22 | cube(size = [dimension_width,dimension_length,dimension_bottom_thickness], center = true); 23 | 24 | translate(v=[arduino_nano_x,0,arduino_nano_z]) { 25 | arduino_nano_enclosure(cut_holes=false); 26 | } 27 | translate(v=[pololu_md01b_x,pololu_md01b_y,pololu_md01b_z]) { 28 | pololu_md01b_mounting_plate(cut_holes=false); 29 | } 30 | } 31 | 32 | translate(v=[arduino_nano_x,0,arduino_nano_z]) { 33 | arduino_nano_enclosure_holes(); 34 | } 35 | translate(v=[pololu_md01b_x,pololu_md01b_y,pololu_md01b_z]) { 36 | pololu_md01b_mounting_plate_holes(); 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /OpenSCAD/banebots/p60.scad: -------------------------------------------------------------------------------- 1 | /* 2 | * +-+ 3 | * | | <-- shaft 4 | * | | 5 | * +-----+ <-- raised edge 6 | * +-------+ <-- top 7 | * |o o| 8 | * |-------| 9 | * | | 10 | * | | 11 | * | | 12 | * |-------| 13 | * |o o| 14 | * +-------+ <-- bottom 15 | * 16 | * || 17 | * 18 | */ 19 | 20 | // Measurements 21 | raised_edge_thickness = 3.67; // This is the protrusion on the front of the motor, designed to house two bearings. 22 | raised_edge_diameter = 35.02; 23 | top_bearing_block_length = 15.13; // This bearing block is wider because it houses two bearings 24 | hole_scale_factor = 1.10; 25 | bottom_to_top = 54.57; 26 | top_to_hole = 1.32; 27 | side_to_hole = 7.05; 28 | hole_diameter = 4.71; 29 | width = 38.18; 30 | gear_housing_diameter = 36.85; 31 | bearing_plate_thickness = 7.70; // the square part only 32 | 33 | // Calculated Dimensions 34 | hole_radius = hole_diameter / 2; 35 | hole_radius_scaled = hole_radius * hole_scale_factor; 36 | gear_housing_radius = gear_housing_diameter/2; 37 | raised_edge_radius = raised_edge_diameter/2; 38 | distance_between_bearing_plates = bottom_to_top - bearing_plate_thickness*2; 39 | gear_housing_length = distance_between_bearing_plates + bearing_plate_thickness + raised_edge_thickness - top_bearing_block_length; 40 | 41 | function banebots_p60_bottom_to_top() = bottom_to_top; 42 | function banebots_p60_top_to_hole() = top_to_hole; 43 | function banebots_p60_hole_radius() = hole_radius; 44 | function banebots_p60_hole_radius_scaled() = hole_radius_scaled; 45 | function banebots_p60_width() = width; 46 | function banebots_p60_bearing_plate_thickness() = bearing_plate_thickness; 47 | function banebots_p60_distance_between_holes() = width - side_to_hole*2 - hole_radius*2; 48 | function banebots_p60_side_to_hole() = side_to_hole; 49 | 50 | module banebots_p60_bottom_bearing_block() { 51 | difference() { 52 | cube(size=[banebots_p60_width(),banebots_p60_width(),banebots_p60_bearing_plate_thickness()],center=true); 53 | // TODO: mounting holes 54 | } 55 | } 56 | 57 | module banebots_p60_gear_housing() { 58 | cylinder(r=gear_housing_radius,h=gear_housing_length, center=true); 59 | } 60 | 61 | module banebots_p60_top_bearing_block() { 62 | union(){ 63 | cube(size=[banebots_p60_width(),banebots_p60_width(),banebots_p60_bearing_plate_thickness()], center=true); 64 | // Raised Edge (this houses the second bearing for the output shaft) 65 | translate(v=[0,0,banebots_p60_bearing_plate_thickness()/2 + raised_edge_thickness/2]) { 66 | cylinder(r=raised_edge_radius,h=raised_edge_thickness, center=true); 67 | } 68 | translate(v=[0,0,-banebots_p60_bearing_plate_thickness()/2 - (top_bearing_block_length - banebots_p60_bearing_plate_thickness() - raised_edge_thickness)/2]) { 69 | cylinder(r=gear_housing_radius,h=top_bearing_block_length - banebots_p60_bearing_plate_thickness() - raised_edge_thickness, center=true); 70 | } 71 | // TODO: mounting holes 72 | } 73 | } 74 | 75 | module banebots_p60() { 76 | // Bottom Bearing Block 77 | translate(v=[banebots_p60_width()/2,0,banebots_p60_width()/2]){ 78 | translate(v=[0,0,banebots_p60_bearing_plate_thickness()/2]) { 79 | color("red") 80 | banebots_p60_bottom_bearing_block(); 81 | } 82 | 83 | // Gearbox Housing 84 | translate(v=[0,0,banebots_p60_bearing_plate_thickness() + gear_housing_length/2]) { 85 | color("green") 86 | banebots_p60_gear_housing(); 87 | } 88 | 89 | // Top Bearing Block 90 | translate(v=[0,0,banebots_p60_bottom_to_top() - banebots_p60_bearing_plate_thickness()/2]) { 91 | banebots_p60_top_bearing_block(); 92 | } 93 | } 94 | 95 | } 96 | 97 | banebots_p60(); 98 | -------------------------------------------------------------------------------- /OpenSCAD/motor_plate/motor_plate.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/createthis/DIYServo/475e1aea15c6f827e2da441293d7af90a5b53c07/OpenSCAD/motor_plate/motor_plate.png -------------------------------------------------------------------------------- /OpenSCAD/motor_plate/motor_plate.scad: -------------------------------------------------------------------------------- 1 | /* Copyright 2013 CreateThis.com 2 | * All Rights Reserved 3 | */ 4 | 5 | include <../resolution.scad> 6 | include 7 | 8 | // Do It 9 | difference(){ 10 | cube(size = [dimension_width,dimension_length,dimension_thickness], center = true); 11 | 12 | // holes 13 | 14 | // top 15 | // right 16 | translate(v = [ dimension_width_center_to_hole_right,dimension_length_middle_to_top_hole_center,0]) { 17 | cylinder(h = dimension_thickness,r = dimension_hole_radius_scaled,center = true, $fn = resolution); 18 | } 19 | // left 20 | translate(v = [ -dimension_width_center_to_hole_right,dimension_length_middle_to_top_hole_center,0]) { 21 | cylinder(h = dimension_thickness,r = dimension_hole_radius_scaled,center = true, $fn = resolution); 22 | } 23 | 24 | // bottom 25 | // right 26 | translate(v = [ dimension_width_center_to_hole_right,-dimension_length_middle_to_top_hole_center,0]) { 27 | cylinder(h = dimension_thickness,r = dimension_hole_radius_scaled,center = true, $fn = resolution); 28 | } 29 | // left 30 | translate(v = [ -dimension_width_center_to_hole_right,-dimension_length_middle_to_top_hole_center,0]) { 31 | cylinder(h = dimension_thickness,r = dimension_hole_radius_scaled,center = true, $fn = resolution); 32 | } 33 | 34 | // middle 35 | // right 36 | translate(v = [ dimension_width_center_to_hole_right,dimension_length_middle_to_middle_hole_center,0]) { 37 | cylinder(h = dimension_thickness,r = dimension_hole_radius_scaled,center = true, $fn = resolution); 38 | } 39 | // left 40 | translate(v = [ -dimension_width_center_to_hole_right,dimension_length_middle_to_middle_hole_center,0]) { 41 | cylinder(h = dimension_thickness,r = dimension_hole_radius_scaled,center = true, $fn = resolution); 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /OpenSCAD/motor_plate/motor_plate_dimensions.scad: -------------------------------------------------------------------------------- 1 | /* Copyright 2013 CreateThis.com 2 | * All Rights Reserved 3 | */ 4 | 5 | include <../resolution.scad> 6 | 7 | /* Motor plate looks like this: 8 | * 9 | * +------+ 10 | * |o o| top 11 | * | | 12 | * | | 13 | * |o o| middle 14 | * | | 15 | * | | 16 | * | | 17 | * |o o| bottom 18 | * +------+ 19 | */ 20 | 21 | // Measured Dimensions 22 | dimension_width = 38.18; 23 | dimension_length = 95.94; 24 | dimension_thickness = 6.29; 25 | dimension_hole_diameter = 4.71; // This accepts a #10-32 x 1/2" screw. 26 | dimension_top_to_hole = 1.32; 27 | dimension_side_to_hole = 7.05; 28 | dimension_middle_top_to_hole = 1.42; 29 | dimension_bottom_to_middle_top = 54.57; 30 | dimension_middle_plate_length = 7.58; 31 | dimension_side_screw_hole_diameter = 3.43; // This accepts a #6-32 screw 32 | 33 | // Calculated Dimensions Big Plate 34 | dimension_hole_diameter_scaled = dimension_hole_diameter * 1.10; // Add 10% to compensate for printer overflow 35 | dimension_hole_radius = dimension_hole_diameter / 2; 36 | dimension_hole_radius_scaled = dimension_hole_diameter_scaled / 2; 37 | dimension_length_middle_to_top_hole_center = dimension_length / 2 - (dimension_top_to_hole + dimension_hole_radius); 38 | dimension_length_middle_to_middle_hole_center = (dimension_bottom_to_middle_top - dimension_middle_top_to_hole - dimension_hole_radius) - dimension_length / 2; 39 | dimension_width_center_to_hole_right = dimension_width / 2 - dimension_side_to_hole - dimension_hole_radius; 40 | 41 | // Calculated Dimensions Gearbox Plate 42 | dimension_gearbox_length = dimension_bottom_to_middle_top; 43 | dimension_gearbox_middle_to_top_hole_center = dimension_gearbox_length / 2 - (dimension_middle_top_to_hole + dimension_hole_radius); 44 | dimension_side_screw_hole_radius = dimension_side_screw_hole_diameter / 2; 45 | dimension_gearbox_through_hole_y = dimension_gearbox_length / 2 - dimension_middle_plate_length - dimension_side_screw_hole_radius; 46 | 47 | -------------------------------------------------------------------------------- /OpenSCAD/motor_plate/motor_plate_mounting_bracket.scad: -------------------------------------------------------------------------------- 1 | /* Copyright 2013 CreateThis.com 2 | * All Rights Reserved 3 | */ 4 | 5 | include <../resolution.scad> 6 | include 7 | use <../arduino_nano_enclosure/arduino_nano_enclosure.scad> 8 | 9 | // Do It 10 | difference(){ 11 | cube(size = [dimension_width,dimension_gearbox_length,dimension_thickness], center = true); 12 | 13 | // holes 14 | 15 | // bottom 16 | // right 17 | translate(v = [ dimension_width_center_to_hole_right,-dimension_gearbox_middle_to_top_hole_center,0]) { 18 | cylinder(h = dimension_thickness,r = dimension_hole_radius_scaled,center = true, $fn = resolution); 19 | } 20 | // left 21 | translate(v = [ -dimension_width_center_to_hole_right,-dimension_gearbox_middle_to_top_hole_center,0]) { 22 | cylinder(h = dimension_thickness,r = dimension_hole_radius_scaled,center = true, $fn = resolution); 23 | } 24 | 25 | // middle 26 | // right 27 | translate(v = [ dimension_width_center_to_hole_right,dimension_gearbox_middle_to_top_hole_center,0]) { 28 | cylinder(h = dimension_thickness,r = dimension_hole_radius_scaled,center = true, $fn = resolution); 29 | } 30 | // left 31 | translate(v = [ -dimension_width_center_to_hole_right,dimension_gearbox_middle_to_top_hole_center,0]) { 32 | cylinder(h = dimension_thickness,r = dimension_hole_radius_scaled,center = true, $fn = resolution); 33 | } 34 | 35 | // side top 36 | translate(v = [0,dimension_gearbox_through_hole_y,0]) { 37 | rotate(a=90, v=[0,1,0]) { 38 | cylinder(h = dimension_width + 0.0001 /* OpenSCAD math bug */,r = dimension_side_screw_hole_radius,center = true, $fn = resolution); 39 | } 40 | } 41 | 42 | translate(v = [0,dimension_gearbox_through_hole_y - arduino_nano_enclosure_distance_between_holes_width(),0]) { 43 | rotate(a=90, v=[0,1,0]) { 44 | cylinder(h = dimension_width + 0.0001 /* OpenSCAD math bug */,r = dimension_side_screw_hole_radius,center = true, $fn = resolution); 45 | } 46 | } 47 | 48 | // Cut hole in middle for faster print times and less waste 49 | cube(size = [dimension_width - dimension_middle_plate_length * 2,dimension_gearbox_length - dimension_middle_plate_length * 2,dimension_thickness], center = true); 50 | } 51 | -------------------------------------------------------------------------------- /OpenSCAD/motor_plate_front/motor_plate_front.scad: -------------------------------------------------------------------------------- 1 | // This part is an adapter that mates a Mad Scientist Hut 10 Bit Magnetic Rotation Encoder: 2 | // http://www.madscientisthut.com/Shopping/agora.cgi?cart_id=5821232.593&product=CNC%20/%20Robotic%20Sensors&user4=Rotary%20Encoder&xm=on 3 | // To a BaneBots bearing block. This allows the absolute position of the Banebots P60 gearbox 4 | // to be read by the MRE at the output shaft. 5 | 6 | // Measured Dimensions 7 | dimension_width = 38.33; 8 | dimension_bearing_ridge_outer_diameter = 31.96; 9 | dimension_bearing_ridge_inner_diameter = 16.77; 10 | dimension_bearing_ridge_height = 1.27; 11 | dimension_screw_head_height = 5.33; 12 | 13 | dimension_raised_circuit_board_mounts = 3.92; 14 | 15 | dimension_bearing_ridge_outer_radius = dimension_bearing_ridge_outer_diameter / 2; 16 | dimension_bearing_ridge_inner_radius = dimension_bearing_ridge_inner_diameter / 2; 17 | 18 | dimension_side_to_hole = 2.21; 19 | dimension_screw_hole_diameter = 3.43; // This accepts a #6-32 x 1/2" screw 20 | dimension_screw_head_diameter = 6.82; // This is the screw head of a #6-32 x 1/2" phillips head screw 21 | 22 | dimension_distance_between_mre_holes_top = 12.28; // distance between screw holes in MRE board, on center 23 | dimension_distance_between_mre_holes_side = 22.80; // distance between screw holes in MRE board, on center 24 | dimension_mre_screw_hole_diameter = 1.99; // accepts tiny self tapping screw (equivalent to drilling a 5/64" hole) 25 | dimension_mre_recess_for_pins_top_to_bottom = 14; // the pins extend below the board a bit, so provide a recess 26 | dimension_mre_recess_for_pins_depth = 2.22; 27 | dimension_mre_width = 18.90; 28 | 29 | resolution = 100; 30 | 31 | // Calculated Dimensions 32 | dimension_thickness = dimension_screw_head_height + dimension_raised_circuit_board_mounts; 33 | dimension_bearing_ridge_height_scaled = dimension_bearing_ridge_height * 1.10; // Add 10% to compensate for plastic droop 34 | dimension_screw_hole_diameter_scaled = dimension_screw_hole_diameter * 1.10; // Add 10% to compensate for printer overflow 35 | dimension_screw_head_diameter_scaled = dimension_screw_head_diameter * 1.10; // Add 10% 36 | dimension_mre_screw_hole_diameter_scaled = dimension_mre_screw_hole_diameter * 1.10; // Add 10% 37 | dimension_screw_hole_radius = dimension_screw_hole_diameter / 2; 38 | dimension_screw_hole_radius_scaled = dimension_screw_hole_diameter_scaled / 2; 39 | dimension_screw_head_radius_scaled = dimension_screw_head_diameter_scaled / 2; 40 | dimension_mre_screw_hole_radius_scaled = dimension_mre_screw_hole_diameter_scaled / 2; 41 | dimension_width_center_to_hole_right = dimension_width / 2 - dimension_side_to_hole - dimension_screw_hole_radius; 42 | dimension_countersink_height = dimension_thickness - dimension_screw_head_height; 43 | dimension_mre_center_to_hole_right = dimension_distance_between_mre_holes_side / 2; 44 | dimension_mre_center_to_hole_top = dimension_distance_between_mre_holes_top / 2; 45 | 46 | // Do It 47 | difference(){ 48 | cube(size = [dimension_width,dimension_width,dimension_thickness], center = true); 49 | 50 | // inner bearing bore 51 | cylinder(h = dimension_thickness,r = dimension_bearing_ridge_inner_radius,center = true, $fn = resolution); 52 | 53 | // raised bearing ridge 54 | translate(v = [ 0,0,dimension_thickness/2 - dimension_bearing_ridge_height_scaled/2 + 0.001 /* compensate for bug in openscad */]) { 55 | cylinder(h = dimension_bearing_ridge_height_scaled,r = dimension_bearing_ridge_outer_radius,center = true, $fn = resolution); 56 | } 57 | 58 | // body mounting holes 59 | 60 | // top 61 | // right 62 | translate(v = [ dimension_width_center_to_hole_right,dimension_width_center_to_hole_right,0]) { 63 | // thread hole 64 | cylinder(h = dimension_thickness,r = dimension_screw_hole_radius_scaled,center = true, $fn = resolution); 65 | 66 | // head countersink 67 | translate(v = [ 0,0,-(dimension_thickness/2) + (dimension_countersink_height)/2]) { 68 | cylinder(h = dimension_countersink_height,r = dimension_screw_head_radius_scaled,center = true, $fn = resolution); 69 | } 70 | } 71 | // left 72 | translate(v = [ -dimension_width_center_to_hole_right,dimension_width_center_to_hole_right,0]) { 73 | // thread hole 74 | cylinder(h = dimension_thickness,r = dimension_screw_hole_radius_scaled,center = true, $fn = resolution); 75 | 76 | // head countersink 77 | translate(v = [ 0,0,-(dimension_thickness/2) + (dimension_countersink_height)/2]) { 78 | cylinder(h = dimension_countersink_height,r = dimension_screw_head_radius_scaled,center = true, $fn = resolution); 79 | } 80 | } 81 | 82 | // bottom 83 | // right 84 | translate(v = [ dimension_width_center_to_hole_right,-dimension_width_center_to_hole_right,0]) { 85 | // thread hole 86 | cylinder(h = dimension_thickness,r = dimension_screw_hole_radius_scaled,center = true, $fn = resolution); 87 | 88 | // head countersink 89 | translate(v = [ 0,0,-(dimension_thickness/2) + (dimension_countersink_height)/2]) { 90 | cylinder(h = dimension_countersink_height,r = dimension_screw_head_radius_scaled,center = true, $fn = resolution); 91 | } 92 | } 93 | // left 94 | translate(v = [ -dimension_width_center_to_hole_right,-dimension_width_center_to_hole_right,0]) { 95 | // thread hole 96 | cylinder(h = dimension_thickness,r = dimension_screw_hole_radius_scaled,center = true, $fn = resolution); 97 | 98 | // head countersink 99 | translate(v = [ 0,0,-(dimension_thickness/2) + (dimension_countersink_height)/2]) { 100 | cylinder(h = dimension_countersink_height,r = dimension_screw_head_radius_scaled,center = true, $fn = resolution); 101 | } 102 | } 103 | 104 | mre_holes(dimension_thickness); 105 | mre_pin_recess(-(dimension_thickness/2) + (dimension_mre_recess_for_pins_depth)/2 - 0.001 /* compensate for bug in openscad */); 106 | } 107 | 108 | module mre_pin_recess(z_offset) { 109 | // mre pin recess 110 | 111 | translate(v = [ 0,0,z_offset]) { 112 | cube(size = [dimension_mre_recess_for_pins_top_to_bottom,dimension_mre_width,dimension_mre_recess_for_pins_depth], center = true); 113 | } 114 | } 115 | 116 | module mre_holes(thickness) { 117 | // mre mounting holes 118 | 119 | // top 120 | // right 121 | translate(v = [ dimension_mre_center_to_hole_right,dimension_mre_center_to_hole_top,0]) { 122 | // thread hole 123 | cylinder(h = thickness,r = dimension_mre_screw_hole_radius_scaled,center = true, $fn = resolution); 124 | } 125 | // left 126 | translate(v = [ -dimension_mre_center_to_hole_right,dimension_mre_center_to_hole_top,0]) { 127 | // thread hole 128 | cylinder(h = thickness,r = dimension_mre_screw_hole_radius_scaled,center = true, $fn = resolution); 129 | } 130 | 131 | // bottom 132 | // right 133 | translate(v = [ dimension_mre_center_to_hole_right,-dimension_mre_center_to_hole_top,0]) { 134 | // thread hole 135 | cylinder(h = thickness,r = dimension_mre_screw_hole_radius_scaled,center = true, $fn = resolution); 136 | } 137 | // left 138 | translate(v = [ -dimension_mre_center_to_hole_right,-dimension_mre_center_to_hole_top,0]) { 139 | // thread hole 140 | cylinder(h = thickness,r = dimension_mre_screw_hole_radius_scaled,center = true, $fn = resolution); 141 | } 142 | 143 | } 144 | -------------------------------------------------------------------------------- /OpenSCAD/motor_plate_front/motor_plate_front_bottom.stl: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/createthis/DIYServo/475e1aea15c6f827e2da441293d7af90a5b53c07/OpenSCAD/motor_plate_front/motor_plate_front_bottom.stl -------------------------------------------------------------------------------- /OpenSCAD/motor_plate_front/motor_plate_front_top.stl: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/createthis/DIYServo/475e1aea15c6f827e2da441293d7af90a5b53c07/OpenSCAD/motor_plate_front/motor_plate_front_top.stl -------------------------------------------------------------------------------- /OpenSCAD/motor_plate_side/motor_plate_side.scad: -------------------------------------------------------------------------------- 1 | include <../resolution.scad> 2 | use <../banebots/p60.scad> 3 | use <../mre_gear_box/bearing_block.scad> 4 | use <../arduino_nano_enclosure/arduino_nano_enclosure.scad> 5 | 6 | // Measured Dimensions 7 | length_scale_factor = 1.01; // scale factor for my printer to make parts fit 8 | dimension_side_length = 103.51; // banebots p60 top to bottom + rs555 top to bottom - p60 top bearing plate thickness 9 | dimension_side_screw_hole_diameter = 3.43; // This accepts a #6-32 screw 10 | 11 | // Calculated Dimensions 12 | dimension_side_length_scaled = dimension_side_length / length_scale_factor; 13 | side_screw_hole_radius = dimension_side_screw_hole_diameter / 2; 14 | dimension_thickness = mre_gearbox_support_width(); 15 | dimension_side_width = banebots_p60_width() + dimension_thickness; 16 | bottom_to_top = banebots_p60_bottom_to_top() - banebots_p60_bearing_plate_thickness(); 17 | bottom_to_top_hole_center = bottom_to_top - banebots_p60_top_to_hole() - banebots_p60_hole_radius(); 18 | 19 | difference() { 20 | cube(size=[dimension_side_width,dimension_side_length_scaled,dimension_thickness]); 21 | 22 | // Cutouts to save plastic and weight 23 | translate(v=[dimension_thickness,banebots_p60_bearing_plate_thickness(),0]){ 24 | cube(size=[ 25 | dimension_side_width - dimension_thickness*2, 26 | banebots_p60_bottom_to_top() - banebots_p60_bearing_plate_thickness()*3, 27 | dimension_thickness 28 | ]); 29 | } 30 | translate(v=[dimension_thickness,banebots_p60_bottom_to_top() - banebots_p60_bearing_plate_thickness(),0]){ 31 | cube(size=[ 32 | dimension_side_width - dimension_thickness*2, 33 | dimension_side_length_scaled - banebots_p60_bottom_to_top(), 34 | dimension_thickness 35 | ]); 36 | } 37 | 38 | 39 | // Mounting holes 40 | translate(v=[0,bottom_to_top_hole_center,0]) { 41 | // left 42 | translate(v=[banebots_p60_side_to_hole() + banebots_p60_hole_radius(),0,0]) { 43 | cylinder(r=banebots_p60_hole_radius_scaled(), h=dimension_thickness, $fn = resolution); 44 | } 45 | // right 46 | translate(v=[banebots_p60_side_to_hole() + banebots_p60_hole_radius() + banebots_p60_distance_between_holes(),0,0]) { 47 | cylinder(r=banebots_p60_hole_radius_scaled(), h=dimension_thickness, $fn = resolution); 48 | } 49 | } 50 | // Side holes 51 | translate(v=[-0.001 /* math fix */,bottom_to_top_hole_center - arduino_nano_enclosure_distance_between_holes_width()/2,dimension_thickness/2]) { 52 | rotate(a=90,v=[0,1,0]) { 53 | cylinder(r=side_screw_hole_radius,h=dimension_side_width + 0.002 /* math fix */, $fn = resolution); 54 | translate(v=[0,arduino_nano_enclosure_distance_between_holes_width(),0]) { 55 | cylinder(r=side_screw_hole_radius,h=dimension_side_width + 0.002 /* math fix */, $fn = resolution); 56 | } 57 | } 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /OpenSCAD/mre_gear_box/bearing_block.scad: -------------------------------------------------------------------------------- 1 | /* Copyright 2013 CreateThis.com 2 | * All Rights Reserved 3 | */ 4 | 5 | include <../resolution.scad> 6 | include 7 | use <../motor_plate_front/motor_plate_front.scad> 8 | 9 | module mre_gearbox_bearing_block() { 10 | difference() { 11 | // main rectangle 12 | cube(size = [bearing_plate_width,bearing_plate_length,total_thickness]); 13 | translate(v=[0,support_width,0]){ 14 | // lid screw holes 15 | 16 | // bottom left 17 | translate(v=[support_width/1.8,-support_width/2.2,0]) { 18 | cylinder( 19 | r=lid_screw_hole_radius, 20 | h=total_thickness + 0.002 /* stupid math bug */, 21 | $fn = resolution 22 | ); 23 | } 24 | 25 | // bottom right 26 | translate(v=[bearing_plate_width - support_width/1.8,-support_width/2.2,0]) { 27 | cylinder( 28 | r=lid_screw_hole_radius, 29 | h=total_thickness + 0.002 /* stupid math bug */, 30 | $fn = resolution 31 | ); 32 | } 33 | 34 | // top left 35 | translate(v=[support_width/1.8,bearing_plate_length -support_width -support_width/1.8,0]) { 36 | cylinder( 37 | r=lid_screw_hole_radius, 38 | h=total_thickness + 0.002 /* stupid math bug */, 39 | $fn = resolution 40 | ); 41 | } 42 | 43 | // top right 44 | translate(v=[bearing_plate_width - support_width/1.8,bearing_plate_length -support_width -support_width/1.8,0]) { 45 | cylinder( 46 | r=lid_screw_hole_radius, 47 | h=total_thickness + 0.002 /* stupid math bug */, 48 | $fn = resolution 49 | ); 50 | } 51 | 52 | // cut out for gearbox 53 | translate(v=[support_width,0,0]) { 54 | cube(size = [gearbox_width,gearbox_width,total_thickness]); 55 | } 56 | 57 | // mounting holes 58 | translate(v=[ 59 | -0.001 /* math bug*/, 60 | dimension_side_to_hole + dimension_hole_radius_scaled, 61 | mounting_hole_z 62 | ]) { 63 | rotate(a=90, v=[0,1,0]) { 64 | cylinder( 65 | r=dimension_hole_radius_scaled, 66 | h=bearing_plate_width + 0.002 /* stupid math bug */, 67 | $fn = resolution 68 | ); 69 | } 70 | } 71 | translate(v=[ 72 | -0.001 /* math bug*/, 73 | dimension_side_to_hole + dimension_distance_between_holes - dimension_hole_radius_scaled, 74 | mounting_hole_z 75 | ]) { 76 | rotate(a=90, v=[0,1,0]) { 77 | cylinder( 78 | r=dimension_hole_radius_scaled, 79 | h=bearing_plate_width + 0.002 /* stupid math bug */, 80 | $fn = resolution 81 | ); 82 | } 83 | } 84 | 85 | // bearing cutout 86 | translate(v=[bearing_x,gearbox_far_edge_to_outside_edge_bearing - mre_bearing_radius_scaled,0]) { 87 | cylinder(r=mre_bearing_radius_scaled, h=total_thickness, $fn = resolution); 88 | 89 | translate(v=[0,0,total_thickness/2]) { 90 | mre_holes(total_thickness + 0.001 /* math bug aggh */); 91 | } 92 | } 93 | } 94 | } 95 | } 96 | 97 | mre_gearbox_bearing_block(); 98 | 99 | function mre_gearbox_total_thickness() = total_thickness; 100 | function mre_gearbox_support_width() = support_width; 101 | -------------------------------------------------------------------------------- /OpenSCAD/mre_gear_box/bearing_block_dimensions.scad: -------------------------------------------------------------------------------- 1 | scale_factor = 1.09; // 9% for easily threaded through holes 2 | bearing_scale_factor = 1.00; // We tried +5% and it was too loose, -5% way too tight. So just nothing this time. 3 | gearbox_width = 38.24; 4 | mre_bearing_diameter = 22.08; 5 | gearbox_far_edge_to_outside_edge_bearing = 63.26; // --> | gearbox | | bearing | <-- 6 | support_width = 6.29; // same as motor plate dimension_thickness 7 | dimension_hole_diameter = 4.71; // This accepts a #10-32 x 1/2" screw. 8 | lid_screw_hole_diameter = 3.43; // This accepts a #6-32 screw 9 | mre_bearing_plate_thickness = 7.70; // This is the thickness of the aluminum gearbox block (the square part) 10 | mre_bearing_raised_edge_thickness = 3.67; // This is the round raised edge on the front of the motor. 11 | 12 | // Spacer 13 | mre_bearing_spacer_height = 4.48; 14 | mre_bearing_spacer_thickness = 3.73; 15 | 16 | // MRE Spacer Plate 17 | mre_spacer_plate_length = 29.13; 18 | mre_spacer_plate_thickness = 2.05; 19 | 20 | 21 | /* Motor plate looks like this: 22 | * 23 | * +------+ 24 | * |o o| top <--- only exists if optional supporting bearing block used. 25 | * | | 26 | * | | 27 | * |o o| middle 28 | * | | 29 | * | | 30 | * | | 31 | * |o o| bottom 32 | * +------+ 33 | * 34 | * Which is confusing, because our mounted plate mounts in the middle of that diagram and looks like this: 35 | * +------+-------+ 36 | * |o o | 37 | * +------+-------+ 38 | */ 39 | 40 | dimension_top_to_hole = 1.42; // same as motor plate dimension_middle_top_to_hole 41 | dimension_side_to_hole = 7.05; // first hole on the y axis 42 | 43 | 44 | // Calculated 45 | lid_screw_hole_radius = lid_screw_hole_diameter/2; 46 | mre_bearing_radius = mre_bearing_diameter / 2; 47 | mre_bearing_radius_scaled = mre_bearing_radius / bearing_scale_factor; 48 | dimension_hole_radius = dimension_hole_diameter/2; 49 | dimension_hole_radius_scaled = dimension_hole_radius * scale_factor; 50 | bearing_gearbox_gap_thickness = gearbox_far_edge_to_outside_edge_bearing - gearbox_width - mre_bearing_diameter; 51 | bearing_plate_width = gearbox_width + support_width * 2; 52 | bearing_plate_length = gearbox_width * 2 + support_width; 53 | dimension_distance_between_holes = gearbox_width - dimension_side_to_hole * 2; 54 | bearing_x = bearing_plate_width / 2; 55 | total_thickness = mre_bearing_plate_thickness + mre_bearing_raised_edge_thickness; 56 | mounting_hole_z = total_thickness - dimension_top_to_hole - dimension_hole_radius_scaled; 57 | 58 | mre_spacer_plate_width = bearing_gearbox_gap_thickness*2 + mre_bearing_diameter; 59 | -------------------------------------------------------------------------------- /OpenSCAD/mre_gear_box/bearing_spacer.scad: -------------------------------------------------------------------------------- 1 | include <../resolution.scad> 2 | include 3 | 4 | difference () { 5 | cylinder(r=mre_bearing_radius_scaled, h=mre_bearing_spacer_height, $fn = resolution); 6 | cylinder(r=mre_bearing_radius_scaled - mre_bearing_spacer_thickness, h = mre_bearing_spacer_height, $fn = resolution); 7 | } 8 | -------------------------------------------------------------------------------- /OpenSCAD/mre_gear_box/bearing_spacer_plate.scad: -------------------------------------------------------------------------------- 1 | include <../resolution.scad> 2 | include 3 | use <../motor_plate_front/motor_plate_front.scad> 4 | 5 | difference() { 6 | cube(size=[mre_spacer_plate_width,mre_spacer_plate_length,mre_spacer_plate_thickness]); 7 | translate (v=[mre_spacer_plate_width/2, mre_spacer_plate_length/2, mre_spacer_plate_thickness/2]) { 8 | cylinder(r=mre_bearing_radius_scaled/1.1 /* scale factor */, h=mre_spacer_plate_thickness, center=true, $fn=resolution); 9 | mre_holes(total_thickness + 0.001 /* math bug aggh */); 10 | mre_pin_recess(0); 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /OpenSCAD/mre_gear_box/gear_dimensions.scad: -------------------------------------------------------------------------------- 1 | /* Copyright 2013 CreateThis.com 2 | * All Rights Reserved 3 | */ 4 | 5 | // Outer diameter = 34.78mm 6 | // Bore Diameter = 12.71 7 | // Pd = (N+2) / OD 8 | // where Pd is Diametral Pitch 9 | // and N is number of teeth 10 | 11 | keyed_shaft_scale_factor = 1.01; // 1% for shaft keyed gear 12 | mre_scale_factor = 1.03; // 3% interference fit 13 | mre_magnet_scale_factor = 1.12; // 12% easy insert but needs superglue to stay; use 10% for dangerously snug. 14 | 15 | // Output Shaft Gear 16 | outer_diameter = 34.78; 17 | bore_diameter = 12.71; 18 | hub_diameter = 22.71; // 6mm thick 19 | number_of_teeth = 17; 20 | key_depth = 1.60; 21 | key_width = 3.03; 22 | key_thickness = 16; // z 23 | gear_thickness = 4; 24 | //rim_thickness = 4; // unused 25 | screw_hole_diameter = 5.87; // unknown screw type, larger than a #10, smaller than 1/4", #11 maybe? 26 | 27 | // 608ZZG Skate Bearing 28 | skate_bearing_thickness = 7; 29 | 30 | // MRE Gear 31 | mre_gear_shaft_diameter = 7.95; // 5/16" 608ZZG Skate Bearing Bore Diameter 32 | mre_gear_shaft_length = 11; 33 | mre_gear_offset = 1.86; // This is the gap between the gear and the motor body 34 | mre_snap_ring_radius = 0.1; 35 | 36 | // MRE magnet 37 | mre_magnet_diameter = 6.10; 38 | mre_magnet_thickness = 3.19; 39 | 40 | // Calculated 41 | diametral_pitch = (number_of_teeth + 1) / outer_diameter; 42 | mre_gear_shaft_radius = mre_gear_shaft_diameter / 2; 43 | mre_gear_shaft_radius_scaled = mre_gear_shaft_radius * mre_scale_factor; 44 | mre_magnet_radius = mre_magnet_diameter / 2; 45 | mre_magnet_radius_scaled = mre_magnet_radius * mre_magnet_scale_factor; 46 | key_depth_scaled = key_depth * keyed_shaft_scale_factor; 47 | bore_diameter_scaled = bore_diameter * keyed_shaft_scale_factor; 48 | mre_shaft_length_total = mre_gear_shaft_length + mre_gear_offset + gear_thickness; 49 | screw_hole_radius = screw_hole_diameter / 2; 50 | -------------------------------------------------------------------------------- /OpenSCAD/mre_gear_box/gearbox_cover.scad: -------------------------------------------------------------------------------- 1 | /* Copyright 2013 CreateThis.com 2 | * All Rights Reserved 3 | */ 4 | 5 | include <../resolution.scad> 6 | include 7 | include 8 | use <../motor_plate_front/motor_plate_front.scad> 9 | 10 | module mre_gearbox_cover() { 11 | difference() { 12 | // main rectangle 13 | cube(size = [bearing_plate_width,bearing_plate_length,gearbox_cover_thickness]); 14 | translate(v=[0,support_width,0]){ 15 | // lid screw holes 16 | 17 | // bottom left 18 | translate(v=[support_width/1.8,-support_width/2.2,0]) { 19 | cylinder( 20 | r=lid_screw_hole_radius, 21 | h=gearbox_cover_thickness + 0.002 /* stupid math bug */, 22 | $fn = resolution 23 | ); 24 | } 25 | 26 | // bottom right 27 | translate(v=[bearing_plate_width - support_width/1.8,-support_width/2.2,0]) { 28 | cylinder( 29 | r=lid_screw_hole_radius, 30 | h=gearbox_cover_thickness + 0.002 /* stupid math bug */, 31 | $fn = resolution 32 | ); 33 | } 34 | 35 | // top left 36 | translate(v=[support_width/1.8,bearing_plate_length -support_width -support_width/1.8,0]) { 37 | cylinder( 38 | r=lid_screw_hole_radius, 39 | h=gearbox_cover_thickness + 0.002 /* stupid math bug */, 40 | $fn = resolution 41 | ); 42 | } 43 | 44 | // top right 45 | translate(v=[bearing_plate_width - support_width/1.8,bearing_plate_length -support_width -support_width/1.8,0]) { 46 | cylinder( 47 | r=lid_screw_hole_radius, 48 | h=gearbox_cover_thickness + 0.002 /* stupid math bug */, 49 | $fn = resolution 50 | ); 51 | } 52 | 53 | // cut out for gears 54 | translate(v=[support_width,0,0]) { 55 | cube(size = [gearbox_width,bearing_plate_length - support_width * 2,gear_cutout_thickness]); 56 | 57 | translate(v=[gearbox_width/2,gearbox_width/2,0]) { 58 | // Output gear cutout 59 | cylinder(r=output_gear_cutout_radius, h=gearbox_cover_thickness, $fn=resolution); 60 | } 61 | } 62 | 63 | // bearing cutout 64 | translate(v=[bearing_x,gearbox_far_edge_to_outside_edge_bearing - mre_bearing_radius_scaled,0]) { 65 | cylinder(r=mre_bearing_radius_scaled, h=gear_cutout_thickness + skate_bearing_thickness, $fn = resolution); 66 | cylinder(r=skate_bearing_inner_race_recess_radius, h=gear_cutout_thickness + skate_bearing_thickness + skate_bearing_inner_race_recess_thickness, $fn = resolution); 67 | } 68 | } 69 | } 70 | } 71 | 72 | mre_gearbox_cover(); 73 | -------------------------------------------------------------------------------- /OpenSCAD/mre_gear_box/gearbox_cover_dimensions.scad: -------------------------------------------------------------------------------- 1 | gear_cover_air_space = 2; 2 | gear_thickness = 5.55; // shoulder measurement from gear down to bearing block. 3 | bearing_cage_cover_thickness = 3; 4 | output_gear_cutout_diameter = 28; 5 | 6 | // FIXME: This needs to be in it's own 608ZZG_skate_bearing.scad 7 | // 608ZZG Skate Bearing 8 | skate_bearing_thickness = 7; 9 | skate_bearing_inner_race_recess_diameter = 12; 10 | skate_bearing_inner_race_recess_thickness = 1; 11 | 12 | // Calculated 13 | output_gear_cutout_radius = output_gear_cutout_diameter / 2; 14 | skate_bearing_inner_race_recess_radius = skate_bearing_inner_race_recess_diameter / 2; 15 | gear_cutout_thickness = gear_thickness + gear_cover_air_space; 16 | gearbox_cover_thickness = skate_bearing_thickness + gear_cutout_thickness + bearing_cage_cover_thickness; 17 | -------------------------------------------------------------------------------- /OpenSCAD/mre_gear_box/mre_gear.scad: -------------------------------------------------------------------------------- 1 | /* Copyright 2013 CreateThis.com 2 | * All Rights Reserved 3 | */ 4 | 5 | use 6 | include 7 | include <../resolution.scad> 8 | 9 | module snap_ring() { 10 | rotate_extrude(convexity = 10) 11 | translate([mre_gear_shaft_radius_scaled, 0, 0]) 12 | circle(r = mre_snap_ring_radius, $fn = resolution); 13 | } 14 | 15 | union () { 16 | // MRE Shaft 17 | difference () { 18 | cylinder (r=mre_gear_shaft_radius_scaled, h=mre_shaft_length_total, $fn = resolution); 19 | 20 | // Magnet recess 21 | translate (v=[0,0,mre_shaft_length_total - mre_magnet_thickness + 0.0001 /* math bug */]) { 22 | cylinder (r=mre_magnet_radius_scaled, h=mre_magnet_thickness, $fn = resolution); 23 | } 24 | } 25 | /* 26 | // Snap Ring 27 | translate (v=[0,0,gear_thickness + mre_gear_offset + skate_bearing_thickness + mre_snap_ring_radius]) { 28 | snap_ring(); 29 | } 30 | */ 31 | gear ( 32 | diametral_pitch=diametral_pitch, 33 | number_of_teeth=number_of_teeth, 34 | hub_thickness=mre_gear_offset+gear_thickness, 35 | gear_thickness=gear_thickness, 36 | rim_thickness=gear_thickness 37 | ); 38 | } 39 | -------------------------------------------------------------------------------- /OpenSCAD/mre_gear_box/mre_gear_plug.scad: -------------------------------------------------------------------------------- 1 | /* Copyright 2013 CreateThis.com 2 | * All Rights Reserved 3 | */ 4 | 5 | include 6 | include <../resolution.scad> 7 | 8 | mre_gearbox_plug_base_thickness = 1.38; // Measured air gap between the bearing and the gear 9 | 10 | // FIXME: This needs to be in it's own 608ZZG_skate_bearing.scad 11 | // 608ZZG Skate Bearing 12 | skate_bearing_thickness = 7; 13 | skate_bearing_inner_race_recess_diameter = 12; 14 | 15 | // Calculated 16 | mre_gearbox_plug_height = mre_gearbox_plug_base_thickness + skate_bearing_thickness; 17 | skate_bearing_inner_race_recess_radius = skate_bearing_inner_race_recess_diameter / 2; 18 | 19 | union () { 20 | // MRE Shaft 21 | difference () { 22 | cylinder (r=mre_gear_shaft_radius_scaled, h=mre_gearbox_plug_height, $fn = resolution); 23 | 24 | } 25 | cylinder (r=skate_bearing_inner_race_recess_radius, h=mre_gearbox_plug_base_thickness, $fn = resolution); 26 | } 27 | -------------------------------------------------------------------------------- /OpenSCAD/mre_gear_box/output_shaft_gear.scad: -------------------------------------------------------------------------------- 1 | /* Copyright 2013 CreateThis.com 2 | * All Rights Reserved 3 | */ 4 | 5 | use 6 | include 7 | include <../resolution.scad> 8 | 9 | difference () { 10 | union () { 11 | // Key 12 | translate(v=[0,bore_diameter_scaled/2 - key_depth/2,key_thickness/2]) { 13 | cube(size=[key_width,key_depth,key_thickness],center=true); 14 | } 15 | 16 | // Gear 17 | gear ( 18 | diametral_pitch=diametral_pitch, 19 | number_of_teeth=number_of_teeth, 20 | bore_diameter=bore_diameter_scaled, 21 | hub_diameter=hub_diameter, 22 | hub_thickness=key_thickness, 23 | gear_thickness=gear_thickness, 24 | rim_thickness=gear_thickness 25 | ); 26 | } 27 | translate (v=[0,0,key_thickness - (key_thickness - gear_thickness) / 2]) { 28 | rotate(a=90,v=[1,0,0]) { 29 | cylinder(r=screw_hole_radius, h=outer_diameter); 30 | } 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /OpenSCAD/pololu_md01b_mounting_plate/pololu_md01b_mounting_plate.scad: -------------------------------------------------------------------------------- 1 | /* Copyright 2013 CreateThis.com 2 | * All Rights Reserved 3 | */ 4 | 5 | include <../resolution.scad> 6 | 7 | // scale factor is used to compensate for tolerance band in manufacturing 8 | scale_factor = 1.10; // 10% 9 | 10 | // PCB looks a bit like this: 11 | // <--width--> 12 | //+----------+ l 13 | //|o o| e 14 | //| | n 15 | //| o| g 16 | //+----------+ th 17 | // Note the missing lower left mounting hole. 18 | 19 | // PCB 20 | dimension_distance_between_top_holes = 31.75; // aka 1.25" 21 | // This is the PCB hole diameter, commented out because we're using a smaller sheet metal screw. 22 | //dimension_hole_diameter = 3.15; // aka 1/8" 23 | dimension_hole_diameter = 2.83; // 4 x 3/8" sheet metal screw 24 | dimension_distance_hole_edge_to_edge_left = 1.67; 25 | dimension_distance_hole_edge_to_edge_top = 1.63; 26 | dimension_distance_hole_edge_to_edge_right = 1.63; 27 | dimension_distance_hole_edge_to_edge_bottom = 1.53; 28 | dimension_width = 38.10; // aka 1.50" 29 | dimension_length = 29.85; // aka 1.175" 30 | dimension_raised_height = 6; // this allows for soldered pins to stick out of bottom of board. 31 | dimension_fourth_hole_shoulder_length = 3.5; 32 | dimension_fourth_hole_shoulder_width = 5; 33 | dimension_pcb_thickness = 1.74; 34 | 35 | // Case 36 | dimension_bottom_thickness = 2.2; 37 | dimension_hole_wall_thickness = 1.74; 38 | // total height = 3/8" or 9.57mm, 9.94mm effective with printer inconsistencies 39 | 40 | // calculated 41 | dimension_width_scaled = dimension_width * scale_factor; 42 | dimension_length_scaled = dimension_length * scale_factor; 43 | dimension_hole_diameter_scaled = dimension_hole_diameter /* * scale_factor */; // not scaling hole for now 44 | dimension_hole_radius = dimension_hole_diameter / 2; 45 | dimension_hole_radius_scaled = dimension_hole_diameter_scaled / 2; 46 | dimension_hole_outer_radius = dimension_hole_diameter / 2 + dimension_hole_wall_thickness; 47 | dimension_height = dimension_raised_height + dimension_bottom_thickness; 48 | dimension_hole_support_z = (dimension_height - dimension_bottom_thickness)/2; 49 | dimension_center_to_hole_right = dimension_width / 2 - dimension_distance_hole_edge_to_edge_right - dimension_hole_radius; 50 | dimension_center_to_hole_left = dimension_center_to_hole_right - dimension_distance_between_top_holes; 51 | dimension_center_to_hole_top = dimension_length / 2 - dimension_distance_hole_edge_to_edge_top - dimension_hole_radius; 52 | dimension_center_to_hole_bottom = -dimension_length / 2 + dimension_distance_hole_edge_to_edge_bottom + dimension_hole_radius; 53 | dimension_center_to_support_bottom = -dimension_length / 2 + dimension_fourth_hole_shoulder_length/2; 54 | dimension_center_to_support_left = -dimension_width / 2 + dimension_fourth_hole_shoulder_width/2; 55 | 56 | module pololu_md01b_mounting_plate(cut_holes=true) { 57 | difference() { 58 | union() { 59 | cube(size = [dimension_width_scaled,dimension_length_scaled,dimension_bottom_thickness], center = true); 60 | 61 | // hole supports 62 | translate(v = [ 0,0,dimension_hole_support_z - 0.001 /* fix OpenSCAD crappy math bug */]) { 63 | // top 64 | // left 65 | translate(v = [ dimension_center_to_hole_left,dimension_center_to_hole_top,0]) { 66 | // support 67 | cylinder(h = dimension_height,r = dimension_hole_outer_radius,center = true, $fn = resolution); 68 | } 69 | // right 70 | translate(v = [ dimension_center_to_hole_right,dimension_center_to_hole_top,0]) { 71 | // support 72 | cylinder(h = dimension_height,r = dimension_hole_outer_radius,center = true, $fn = resolution); 73 | } 74 | // bottom 75 | // right 76 | translate(v = [ dimension_center_to_hole_right,dimension_center_to_hole_bottom,0]) { 77 | // support 78 | cylinder(h = dimension_height,r = dimension_hole_outer_radius,center = true, $fn = resolution); 79 | } 80 | // left 81 | translate(v = [ dimension_center_to_support_left,dimension_center_to_support_bottom,0]) { 82 | // support 83 | cube(size = [dimension_fourth_hole_shoulder_width,dimension_fourth_hole_shoulder_length,dimension_height], center = true); 84 | } 85 | 86 | } 87 | } 88 | 89 | if (cut_holes) { 90 | pololu_md01b_mounting_plate_holes(); 91 | } 92 | } 93 | } 94 | 95 | module pololu_md01b_mounting_plate_holes() { 96 | // holes 97 | translate(v = [ 0,0,dimension_hole_support_z - 0.001 /* fix OpenSCAD crappy math bug */]) { 98 | // top 99 | // left 100 | translate(v = [ dimension_center_to_hole_left,dimension_center_to_hole_top,0]) { 101 | // hole 102 | cylinder(h = dimension_height*2,r = dimension_hole_radius_scaled,center = true, $fn = resolution); 103 | } 104 | // right 105 | translate(v = [ dimension_center_to_hole_right,dimension_center_to_hole_top,0]) { 106 | // support 107 | cylinder(h = dimension_height*2,r = dimension_hole_radius_scaled,center = true, $fn = resolution); 108 | } 109 | // bottom right 110 | translate(v = [ dimension_center_to_hole_right,dimension_center_to_hole_bottom,0]) { 111 | // support 112 | cylinder(h = dimension_height*2,r = dimension_hole_radius_scaled,center = true, $fn = resolution); 113 | } 114 | } 115 | } 116 | 117 | function pololu_md01b_mounting_plate_width() = dimension_width_scaled; 118 | function pololu_md01b_mounting_plate_length() = dimension_length_scaled; 119 | function pololu_md01b_mounting_plate_height() = dimension_height; 120 | function pololu_md01b_mounting_plate_bottom_thickness() = dimension_bottom_thickness; 121 | 122 | pololu_md01b_mounting_plate(); 123 | -------------------------------------------------------------------------------- /OpenSCAD/resolution.scad: -------------------------------------------------------------------------------- 1 | resolution = 100; 2 | -------------------------------------------------------------------------------- /PololuDriver/PololuDriver.cpp: -------------------------------------------------------------------------------- 1 | #include "PololuDriver.h" 2 | 3 | PololuDriver::PololuDriver(byte pwmPin, byte inA, byte inB) 4 | { 5 | m_pwm = pwmPin; 6 | m_inA = inA; 7 | m_inB = inB; 8 | 9 | pinMode(inA, OUTPUT); //can send +/0 voltage 3.3v/0 10 | pinMode(inB, OUTPUT); 11 | analogWrite(m_pwm, 0); 12 | } 13 | 14 | void PololuDriver::SetSpeed(byte speed) 15 | { 16 | analogWrite(m_pwm, speed); 17 | } 18 | 19 | void PololuDriver::Run(byte direction) 20 | { 21 | switch (direction) 22 | { 23 | case POLOLU_STOP: 24 | digitalWrite(m_inA, LOW); 25 | digitalWrite(m_inB, LOW); 26 | break; 27 | case POLOLU_FORWARD: 28 | digitalWrite(m_inA, HIGH); 29 | digitalWrite(m_inB, LOW); 30 | break; 31 | case POLOLU_REVERSE : 32 | digitalWrite(m_inA, LOW); 33 | digitalWrite(m_inB, HIGH); 34 | break; 35 | } 36 | } 37 | 38 | void PololuDriver::Run(byte direction, byte speed) 39 | { 40 | SetSpeed(speed); 41 | Run(direction); 42 | } 43 | -------------------------------------------------------------------------------- /PololuDriver/PololuDriver.h: -------------------------------------------------------------------------------- 1 | #include "Arduino.h" 2 | 3 | #define POLOLU_STOP 0 4 | #define POLOLU_FORWARD 1 5 | #define POLOLU_REVERSE 2 6 | 7 | class PololuDriver 8 | { 9 | public: 10 | PololuDriver(byte pwmPin, byte inA, byte inB); 11 | void SetSpeed(byte speed); 12 | void Run(byte direction); 13 | void Run(byte direction, byte speed); 14 | private: 15 | byte m_pwm; 16 | byte m_inA; 17 | byte m_inB; 18 | }; 19 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | DIYServo 2 | ======== 3 | 4 | http://www.diyservo.com 5 | 6 | DIY Servo Project - Create your own servo using any motor of your choosing 7 | 8 | 9 | This servo uses an Arduino Nano as a controller, and a Pololu MD01B as a motor driver. 10 | The prototype uses a Banebots P60 gearbox (planetary gearing) mated to an RS555 motor. Substitute any 12V motor 11 | of your choosing. For example, a 12V windshield wiper motor (worm gear) would work, or smaller hobby robotics 12 | motors. 13 | 14 | Video of latest gear driven MRE in action: 15 | http://youtu.be/2uWNyV8dUlA 16 | 17 | Older video of bearing plate mounted MRE in action: 18 | http://youtu.be/V_V_hvIjvC8 19 | 20 | Bill of Materials (BOM): https://docs.google.com/spreadsheet/ccc?key=0AlOm0VEWX2qMdGIxMThxUHNPeFVPeEotaU9RSDRENGc&usp=sharing 21 | 22 | Creative Commons License
This work is licensed under a Creative Commons Attribution-ShareAlike 3.0 Unported License. 23 | -------------------------------------------------------------------------------- /diyservo/diyservo.ino: -------------------------------------------------------------------------------- 1 | /* 2 | DIY Servo - Arduino driving VNH2SP30 Motor Driver Carrier MD01B 3 | 4 | This work is licensed under the Creative Commons Attribution-ShareAlike 3.0 Unported License. To view a copy of this license, visit http://creativecommons.org/licenses/by-sa/3.0/ or send a letter to Creative Commons, 444 Castro Street, Suite 900, Mountain View, California, 94041, USA. 5 | */ 6 | 7 | #include 8 | #include 9 | #include 10 | 11 | #define ENCODER_A_PIN 2 12 | #define ENCODER_B_PIN 3 13 | 14 | // PID Variables 15 | double currentPosition = 310; 16 | double distance = 0; // distance in degrees from currentPosition to positionGoal 17 | double distanceGoal = 0; // we always want the motor to be right on the money 18 | double motorSpeed = 0; 19 | double positionGoal = 120; 20 | double kp=0.000001, ki=0, kd=40; 21 | /* kd=0.005 kind of stable */ 22 | double upperSpeedLimit = 255; 23 | double lowerSpeedLimit = 33; 24 | 25 | // AutoTune Library Variables 26 | double aTuneStep=80, aTuneNoise=1, aTuneStartValue=(upperSpeedLimit - lowerSpeedLimit) / 2 + lowerSpeedLimit; 27 | unsigned int aTuneLookBack=20; 28 | byte ATuneModeRemember=2; 29 | 30 | PololuDriver myPololuDriver(11,10,12); // initialize instance of class 31 | 32 | const int ledPin = 13; //LED connected to digital pin 13 33 | const int clockPin = 7; //output to clock 34 | const int CSnPin = 6; //output to chip select 35 | const int inputPin = 2; //read AS5040 36 | 37 | int debug = 1; //SET THIS TO 0 TO DISABLE PRINTING OF ERROR CODES 38 | boolean tuning = false; // Set this to true to autotune PID values 39 | 40 | String currentState = "stop"; 41 | String lastState = "stop"; 42 | long lastAngle = 0; 43 | 44 | //Specify the links and initial tuning parameters 45 | PID myPID(&distance, &motorSpeed, &distanceGoal,kp,ki,kd, DIRECT); 46 | PID_ATune aTune(¤tPosition, &motorSpeed); 47 | 48 | // the setup routine runs once when you press reset: 49 | void setup() { 50 | Serial.begin(19200); 51 | Serial.setTimeout(50); 52 | Serial.println("Started"); 53 | 54 | pinMode(ENCODER_A_PIN, INPUT); 55 | pinMode(ENCODER_B_PIN, INPUT); 56 | 57 | pinMode(ledPin, OUTPUT); // visual signal of I/O to chip 58 | pinMode(clockPin, OUTPUT); // SCK 59 | pinMode(CSnPin, OUTPUT); // CSn -- has to toggle high and low to signal chip to start data transfer 60 | pinMode(inputPin, INPUT); // SDA 61 | 62 | myPololuDriver.Run(POLOLU_STOP); 63 | 64 | currentPosition = read_angle(); 65 | 66 | //turn the PID on 67 | myPID.SetMode(AUTOMATIC); 68 | myPID.SetOutputLimits(lowerSpeedLimit,upperSpeedLimit); 69 | 70 | if(tuning) 71 | { 72 | tuning=false; 73 | changeAutoTune(); 74 | tuning=true; 75 | Serial.println("tuning mode"); 76 | } 77 | } 78 | 79 | long angle_diff(long angle1, long angle2) { 80 | return (abs(angle1 + 180 - angle2) % 360 - 180); 81 | } 82 | 83 | boolean should_go_forward(long angle1, long angle2) { 84 | return ((angle1 - angle2 + 360)%360>180); 85 | } 86 | 87 | // the loop routine runs over and over again forever: 88 | void loop() { 89 | lastState = currentState; 90 | 91 | currentPosition = read_angle(); 92 | distance = abs(angle_diff(currentPosition, positionGoal)); 93 | 94 | if(tuning) 95 | { 96 | byte val = (aTune.Runtime()); 97 | if (val!=0) 98 | { 99 | tuning = false; 100 | } 101 | if(!tuning) 102 | { //we're done, set the tuning parameters 103 | kp = aTune.GetKp(); 104 | ki = aTune.GetKi(); 105 | kd = aTune.GetKd(); 106 | myPID.SetTunings(kp,ki,kd); 107 | AutoTuneHelper(false); 108 | Serial.print("kp: ");Serial.print(myPID.GetKp());Serial.print(" "); 109 | Serial.print("ki: ");Serial.print(myPID.GetKi());Serial.print(" "); 110 | Serial.print("kd: ");Serial.print(myPID.GetKd());Serial.println(); 111 | } 112 | } 113 | else myPID.Compute(); 114 | 115 | myPololuDriver.SetSpeed((byte) motorSpeed); 116 | 117 | // send data only when you receive data: 118 | if (Serial.available() > 0) { 119 | myPololuDriver.Run(POLOLU_STOP); 120 | currentState = "stop"; 121 | lastState = "stop"; 122 | // read the incoming byte: 123 | positionGoal = (double) Serial.parseInt(); 124 | 125 | // say what you got: 126 | Serial.print("I received: "); 127 | Serial.println(positionGoal, DEC); 128 | Serial.print("myangle: "); 129 | Serial.println(currentPosition, DEC); 130 | 131 | //if((positionGoal==0 && !tuning) || (positionGoal!=0 && tuning))changeAutoTune(); 132 | } else { 133 | if (abs(angle_diff(lastAngle,currentPosition)) > 1) { 134 | //Serial.print("angle_diff: "); 135 | //Serial.println(angle_diff(currentPosition, positionGoal), DEC); 136 | } 137 | 138 | if(tuning){ 139 | //Serial.println("tuning mode"); 140 | } 141 | } 142 | 143 | if (abs(angle_diff(currentPosition, positionGoal)) == 0 /* 0 degree hysterisis */) { 144 | if (lastState != "stop") { 145 | /* 146 | Serial.println("stop"); 147 | Serial.print("currentPosition: "); 148 | Serial.println(currentPosition, DEC); 149 | */ 150 | myPololuDriver.SetSpeed((byte)motorSpeed); 151 | currentState = "stop"; 152 | myPololuDriver.Run(POLOLU_STOP); 153 | } 154 | } else { 155 | if (!should_go_forward(currentPosition, positionGoal)) { 156 | /* 157 | Serial.print("should go forward"); 158 | Serial.print(",distance="); 159 | Serial.print(distance,DEC); 160 | Serial.print(",motorSpeed="); 161 | Serial.print(motorSpeed,DEC); 162 | Serial.print(",currentPosition="); 163 | Serial.print(currentPosition,DEC); 164 | Serial.print(",positionGoal="); 165 | Serial.println(positionGoal,DEC); 166 | */ 167 | if (lastState != "forward") { 168 | // Serial.println("forward"); 169 | myPololuDriver.SetSpeed((byte)motorSpeed); 170 | currentState = "forward"; 171 | myPololuDriver.Run(POLOLU_FORWARD); 172 | } 173 | } else { 174 | /* 175 | Serial.print("should reverse"); 176 | Serial.print(",distance="); 177 | Serial.print(distance,DEC); 178 | Serial.print(",motorSpeed="); 179 | Serial.print(motorSpeed,DEC); 180 | Serial.print(",currentPosition="); 181 | Serial.print(currentPosition,DEC); 182 | Serial.print(",positionGoal="); 183 | Serial.println(positionGoal,DEC); 184 | */ 185 | 186 | if (lastState != "reverse") { 187 | // Serial.println("reverse"); 188 | myPololuDriver.SetSpeed((byte)motorSpeed); 189 | currentState = "reverse"; 190 | myPololuDriver.Run(POLOLU_REVERSE); 191 | } 192 | } 193 | } 194 | lastAngle = currentPosition; 195 | } 196 | 197 | long read_angle() 198 | { 199 | int inputstream = 0; //one bit read from pin 200 | long packeddata = 0; //two bytes concatenated from inputstream 201 | long angle = 0; //holds processed angle value 202 | long anglemask = 65472; //0x1111111111000000: mask to obtain first 10 digits with position info 203 | long statusmask = 63; //0x000000000111111; mask to obtain last 6 digits containing status info 204 | long statusbits; //holds status/error information 205 | int DECn; //bit holding decreasing magnet field error data 206 | int INCn; //bit holding increasing magnet field error data 207 | int OCF; //bit holding startup-valid bit 208 | int COF; //bit holding cordic DSP processing error data 209 | int LIN; //bit holding magnet field displacement error data 210 | int shortdelay = 40; // this is the microseconds of delay in the data clock 211 | int longdelay = 1; // this is the milliseconds between readings 212 | 213 | // CSn needs to cycle from high to low to initiate transfer. Then clock cycles. As it goes high 214 | // again, data will appear on sda 215 | digitalWrite(CSnPin, HIGH); // CSn high 216 | digitalWrite(clockPin, HIGH); // CLK high 217 | //delay(longdelay);// time between readings 218 | delayMicroseconds(shortdelay); // delay for chip initialization 219 | digitalWrite(ledPin, HIGH); // signal start of transfer with LED 220 | digitalWrite(CSnPin, LOW); // CSn low: start of transfer 221 | delayMicroseconds(shortdelay); // delay for chip initialization 222 | digitalWrite(clockPin, LOW); // CLK goes low: start clocking 223 | delayMicroseconds(shortdelay); // hold low 224 | for (int x=0; x <16; x++) // clock signal, 16 transitions, output to clock pin 225 | { 226 | digitalWrite(clockPin, HIGH); //clock goes high 227 | delayMicroseconds(shortdelay); // 228 | inputstream =digitalRead(inputPin); // read one bit of data from pin 229 | //Serial.print(inputstream, DEC); 230 | packeddata = ((packeddata << 1) + inputstream);// left-shift summing variable, add pin value 231 | digitalWrite(clockPin, LOW); 232 | delayMicroseconds(shortdelay); // end of one clock cycle 233 | } 234 | // end of entire clock cycle 235 | //Serial.println(" "); 236 | digitalWrite(ledPin, LOW); // signal end of transmission 237 | // lots of diagnostics for verifying bitwise operations 238 | //Serial.print("packed:"); 239 | //Serial.println(packeddata,DEC); 240 | //Serial.print("pack bin: "); 241 | // Serial.println(packeddata,BIN); 242 | angle = packeddata & anglemask; // mask rightmost 6 digits of packeddata to zero, into angle. 243 | //Serial.print("mask: "); 244 | //Serial.println(anglemask, BIN); 245 | //Serial.print("bin angle:"); 246 | //Serial.println(angle, BIN); 247 | //Serial.print("angle: "); 248 | //Serial.println(angle, DEC); 249 | angle = (angle >> 6); // shift 16-digit angle right 6 digits to form 10-digit value 250 | //Serial.print("angleshft:"); 251 | //Serial.println(angle, BIN); 252 | //Serial.print("angledec: "); 253 | //Serial.println(angle, DEC); 254 | angle = angle * 0.3515; // angle * (360/1024) == actual degrees 255 | //Serial.print("angle: "); // and, finally, print it. 256 | //Serial.println(angle, DEC); 257 | //Serial.println("--------------------"); 258 | //Serial.print("raw: "); // this was the prefix for the bit-by-bit diag output inside the loop. 259 | if (debug) 260 | { 261 | statusbits = packeddata & statusmask; 262 | DECn = statusbits & 2; // goes high if magnet moved away from IC 263 | INCn = statusbits & 4; // goes high if magnet moved towards IC 264 | LIN = statusbits & 8; // goes high for linearity alarm 265 | COF = statusbits & 16; // goes high for cordic overflow: data invalid 266 | OCF = statusbits & 32; // this is 1 when the chip startup is finished. 267 | if (DECn && INCn) { Serial.println("magnet moved out of range"); } 268 | else 269 | { 270 | if (DECn) { Serial.println("magnet moved away from chip"); } 271 | if (INCn) { Serial.println("magnet moved towards chip"); } 272 | } 273 | if (LIN) { Serial.println("linearity alarm: magnet misaligned? Data questionable."); } 274 | if (COF) { Serial.println("cordic overflow: magnet misaligned? Data invalid."); } 275 | } 276 | 277 | return (double) angle; 278 | 279 | packeddata = 0; // reset both variables to zero so they don't just accumulate 280 | angle = 0; 281 | } 282 | 283 | void changeAutoTune() 284 | { 285 | if(!tuning) 286 | { 287 | //Set the output to the desired starting frequency. 288 | motorSpeed=aTuneStartValue; 289 | aTune.SetNoiseBand(aTuneNoise); 290 | aTune.SetOutputStep(aTuneStep); 291 | aTune.SetLookbackSec((int)aTuneLookBack); 292 | AutoTuneHelper(true); 293 | tuning = true; 294 | } 295 | else 296 | { //cancel autotune 297 | aTune.Cancel(); 298 | tuning = false; 299 | AutoTuneHelper(false); 300 | } 301 | } 302 | 303 | void AutoTuneHelper(boolean start) 304 | { 305 | if(start) 306 | ATuneModeRemember = myPID.GetMode(); 307 | else 308 | myPID.SetMode(ATuneModeRemember); 309 | } 310 | -------------------------------------------------------------------------------- /docs/WiringMadScientistHutMRE.txt: -------------------------------------------------------------------------------- 1 | I've gotten an AS5040 10-bit magnetic rotary encoder, and an AS5045 12-bit, working, checking all the non-programmed interfaces. Both can be one-time programmed to output different code schemes, but they're not very useful for what I need so I'm not messing with them. 2 | In both cases I piggybacked the chip/breakout board off an Arduino, using the 3.3v supply. I rather randomly chose to use pins 2, 6, and 7 of the Arduino for the digital input: 6 is a chip select that also signals the start of an interface round, 7 acts as the clock from the Arduino to the chip, and 2 acts as the data transfer from the chip to the Arduino. These are trivially remapped. 3 | The code includes a debug setting that'll print out any faults the AS504x notices, but if you turn off the debug setting you'll just get degrees out. It reads from the chip and transmits to the host computer roughly once a second. 4 | 5 | -- John, Mon Dec 13, 2010 11:14 pm 6 | http://www.madscientisthut.com 7 | 8 | More succinctly: 9 | Arduino Nano - AS5040 Board 10 | GND - GND 11 | 3v3 - VCC (+3.3v) 12 | 2 - SD Out 13 | 6 - CSEL 14 | 7 - CLK_IN 15 | -------------------------------------------------------------------------------- /docs/WiringPololuMDB01.txt: -------------------------------------------------------------------------------- 1 | Arduino Nano - Pololu MDB01 2 | 10 - INa 3 | 11 - PWM 4 | 12 - INb 5 | 5V - +5V (IN) 6 | GND - GND 7 | -------------------------------------------------------------------------------- /docs/pololu_mdb01_pinout.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/createthis/DIYServo/475e1aea15c6f827e2da441293d7af90a5b53c07/docs/pololu_mdb01_pinout.jpg --------------------------------------------------------------------------------