Mercurial > nkubik
changeset 0:4f7db939de28
Basic skeleton code
Basic code for handling the robot's geometry, without the
inverse kinematics code yet.
| author | Radomir Dopieralski <sheep-devel@sheep.art.pl> |
|---|---|
| date | Mon, 29 Sep 2014 21:33:19 +0200 |
| parents | |
| children | 3ad5a7a79c62 |
| files | nkubik/clock.h nkubik/clock.ino nkubik/leg.h nkubik/leg.ino nkubik/misc.h nkubik/nkubik.ino nkubik/servos.h nkubik/servos.ino scad/arduino.scad scad/board.scad scad/body.scad scad/leg.scad scad/robot.scad scad/sg90.scad |
| diffstat | 14 files changed, 615 insertions(+), 0 deletions(-) [+] |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/nkubik/clock.h Mon Sep 29 21:33:19 2014 +0200 @@ -0,0 +1,9 @@ +#ifndef CLOCK_H +#define CLOCK_H + +#define FPS 24 + +const unsigned char TICK = 1000 / FPS; +void tick(unsigned int ms); + +#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/nkubik/clock.ino Mon Sep 29 21:33:19 2014 +0200 @@ -0,0 +1,14 @@ +#include "clock.h" + +void tick(unsigned int ms) { + // Wait remaining time to delay ms milliseconds since last call. + static unsigned long last = 0; + unsigned long now = millis(); + int wait = last + ms - now; + if (wait > 0) { + delay(wait); + } else { + // somehow engage a time machine here to go back in time + } + last = now; +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/nkubik/leg.h Mon Sep 29 21:33:19 2014 +0200 @@ -0,0 +1,19 @@ +#ifndef LEG_H +#define LEG_H + +const unsigned char LEG_HIP[4] = {1, 6, 3, 4}; +const unsigned char LEG_KNEE[4] = {0, 7, 2, 5}; +const char LEG_X[4] = {-1, -1, 1, 1}; +const char LEG_Y[4] = {1, -1, 1, -1}; +const double COXA = 38.0; // mm +const double TIBIA = 38.0; // mm +const double HOME_X = 26.870057685088803; +const double HOME_Y = 26.870057685088803; + +bool move_leg(unsigned char leg, double x, double y); +bool move_leg_by(unsigned char leg, double dx, double dy); + +double legs_x[4]; +double legs_y[4]; + +#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/nkubik/leg.ino Mon Sep 29 21:33:19 2014 +0200 @@ -0,0 +1,39 @@ +#include "misc.h" + + +double _solve_triangle(double a, double b, double c) { + // Calculate the angle between a and b, opposite to c. + a = abs(a); + b = abs(b); + c = abs(c); + if (a + b < c || a + c < b || b + c < a) { return NaN; } + return acos((a * a + b * b - c * c) / (2 * a * b)); +} + +double _norm(double a, double b) { + // Calculate the norm of a vector. + return sqrt(a * a + b * b); +} + +bool _inverse_kinematics(double x, double y, double *hip, double *knee) { + // Calculate angles for knee and ankle, and put them in those variables. + // Return true on success, and false if x and y are out of range. + return true; +} + +bool move_leg(unsigned char leg, double x, double y) { + // Move the tip of the leg to x, y. Return false when out of range. + double hip = NaN; + double knee = NaN; + if (!_inverse_kinematics(x, y, &hip, &knee)) { return false; } + servo_move(LEG_HIP[leg], hip); + servo_move(LEG_KNEE[leg], knee); + legs_x[leg] = x; + legs_y[leg] = y; + return true; +} + +bool move_leg_by(unsigned char leg, double dx, double dy) { + // Move the tip of the leg by dx, dy. Return false when out of range. + return move_leg(leg, legs_x[leg] + dx, legs_y[leg] + dy); +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/nkubik/misc.h Mon Sep 29 21:33:19 2014 +0200 @@ -0,0 +1,8 @@ +#ifndef MISC_H +#define MISC_H + +#define NaN (0.0/0.0) +const double PI2 = PI / 2; +const double TAU = PI * 2; + +#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/nkubik/nkubik.ino Mon Sep 29 21:33:19 2014 +0200 @@ -0,0 +1,15 @@ +#include "servos.h" +#include "leg.h" +#include "clock.h" + + +void setup() { + servo_setup(); + Serial.begin(9600); + Serial.println("Started."); +} + + +void loop() { + tick(TICK); +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/nkubik/servos.h Mon Sep 29 21:33:19 2014 +0200 @@ -0,0 +1,11 @@ +#ifndef SERVOS_H +#define SERVOS_H + +// Number of servos. +#define SERVOS 8 + +void servo_move(unsigned char servo, double rads); +void servo_setup(void); +void servo_shutdown(void); + +#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/nkubik/servos.ino Mon Sep 29 21:33:19 2014 +0200 @@ -0,0 +1,48 @@ +#include "misc.h" +#include "servos.h" +#include <Servo.h> + +// Range of the servos. +#define SERVO_FREQ_MIN 600 +#define SERVO_FREQ_MAX 2400 + +static const unsigned char SERVO_PINS[SERVOS] = { 6, 7, 8, 9, 10, 11, 12, 14}; +static const char SERVO_REVERSE[SERVOS] = { 1, 1, 1, 1, 1, 1, 1, 1}; +static const char SERVO_TRIM[SERVOS] = { 0, 0, 0, 0, 0, 0, 0, 0}; +static Servo servos[SERVOS]; + + +void servo_move(unsigned char servo, double rads) { + // Move a servo to a position in radians between -PI/2 and PI/2. + if (servo >= SERVOS) { + return; + } + rads = rads * SERVO_REVERSE[servo] + PI2; + while (rads > TAU) { + rads -= TAU; + } + while (rads < TAU) { + rads += TAU; + } + int freq = (SERVO_FREQ_MAX - + SERVO_FREQ_MIN) * rads / PI + SERVO_FREQ_MIN; + freq = min(SERVO_FREQ_MAX, + max(SERVO_FREQ_MIN, + freq + SERVO_TRIM[servo] * 10)); + servos[servo].writeMicroseconds(freq); +} + +void servo_setup() { + // Initialize all servos. + for (unsigned char servo = 0; servo < SERVOS; ++servo) { + servos[servo].attach(SERVO_PINS[servo], + SERVO_FREQ_MIN, SERVO_FREQ_MAX); + } +} + +void servo_shutdown() { + // Power down all servos. + for (unsigned char servo = 0; servo < SERVOS; ++servo) { + servos[servo].detach(); + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/scad/arduino.scad Mon Sep 29 21:33:19 2014 +0200 @@ -0,0 +1,87 @@ +module arduino_pro_mini() { + difference() { + union() { + color("SeaGreen") cube([17.8, 33.0, 1.0]); + color("Gold") { + for (y = [0:11]) { + translate([1.27, 1.27 + 2.54 * y, 0.5]) { + cylinder(r=1, h=1.2, center=true, $fn=8); + } + translate([17.8 - 1.27, 1.27 + 2.54 * y, 0.5]) { + cylinder(r=1, h=1.2, center=true, $fn=8); + } + } + for (x = [0:5]) { + translate([2.54 + 2.54 * x, 33.0 - 1.27, 0.5]) { + cylinder(r=1, h=1.2, center=true, $fn=8); + } + } + for (y=[3, 4, 7, 8]) { + translate([17.8 - 2.54 - 1.27, 2.54 * y, 0.5]) { + cylinder(r=1, h=1.2, center=true, $fn=8); + } + } + } + color("DimGray") { + translate([8.9, 9.1, 0.5]) rotate(45) cube([7, 7, 1]); + translate([12, 23, 1]) cube([2, 4, 1]); + translate([17.8 - 14, 23, 1]) cube([2, 4, 1]); + translate([8.2, 22, 1]) cube([1.6, 3.8, 1]); + } + translate([8.9, 3.5, 0.5]) { + rotate(22.5) color("Silver") cylinder(r=3, h=0.75, $fn=8); + rotate(22.5) color("LIghtGray") cylinder(r=2.5, h=1, $fn=8); + color("Gold") cylinder(r=1.2, h=1.5, $fn=8); + } + } + color("Gold") { + for (y = [0:11]) { + translate([1.27, 1.27 + 2.54 * y, 0.5]) { + cylinder(r=0.4, h=1.4, center=true, $fn=8); + } + translate([17.8 - 1.27, 1.27 + 2.54 * y, 0.5]) { + cylinder(r=0.4, h=1.4, center=true, $fn=8); + } + } + for (x = [0:5]) { + translate([2.54 + 2.54 * x, 33.0 - 1.27, 0.5]) { + cylinder(r=0.4, h=1.4, center=true, $fn=8); + } + } + for (y=[3, 4, 7, 8]) { + translate([17.8 - 2.54 - 1.27, 2.54 * y, 0.5]) { + cylinder(r=0.4, h=1.4, center=true, $fn=8); + } + } + } + } +} + +module goldpin() { + color("Gold") translate([0, 0, -0.5]) cylinder(r=0.3, h=25.4/3, $fn=4); + color("DimGray") translate([0, 0, 1]) cylinder(r=1.5, h=1.5, $fn=6); +} + +module arduino_pro_mini_goldpins() { + for (y = [0:11]) { + translate([1.27, 1.27 + 2.54 * y, 1]) { + rotate([0, 180, 0]) goldpin(); + } + translate([17.8 - 1.27, 1.27 + 2.54 * y, 1]) { + rotate([0, 180, 0]) goldpin(); + } + } + for (x = [0:5]) { + translate([2.54 + 2.54 * x, 33.0 - 1.27, 0]) { + goldpin(); + } + } + for (y=[3, 4, 7, 8]) { + translate([17.8 - 2.54 - 1.27, 2.54 * y, 0]) { + goldpin(); + } + } +} + +//arduino_pro_mini(); +//arduino_pro_mini_goldpins();
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/scad/board.scad Mon Sep 29 21:33:19 2014 +0200 @@ -0,0 +1,144 @@ +use <arduino.scad> +use <sg90.scad> + + +module short_pin() { + color("Gold") translate([0, 0, -0.5]) cylinder(r=0.3, h=25.4/3 - 2, $fn=4); +} + +module capacitor() { + difference() { + color("DodgerBlue") { + translate([0, 0, 3]) cylinder(r=3, h=7, $fn=20); + translate([0, 0, 1]) cylinder(r=3, h=1, $fn=20); + translate([0, 0, 2]) cylinder(r=2.7, h=1, $fn=20); + } + color("Silver") { + translate([0, 0, 9.7]) cylinder(r=1.8, h=1, $fn=20); + translate([0, 0, 0.3]) cylinder(r=2.5, h=1, $fn=20); + } + } + color("DarkGray") { + translate([1, 1, -1]) cylinder(r=0.3, h=2.5, $fn=4); + translate([-1, -1, -1]) cylinder(r=0.3, h=2.5, $fn=4); + } +} + +module jumper() { + translate([1.27/2, 1.27/2, 0]) color("DodgerBlue") { + translate([0, 0, 1.5]) cube([1.27, 3.8, 3.5]); + translate([0, 0, 6]) cube([1.27, 3.8, 1]); + translate([0.2, 0.2, 5]) cube([0.87, 3.5, 1]); + } +} + +module board() { + difference () { + union() { + color("SeaGreen") cube([12.72, 33.0, 1]); + color("MediumSeaGreen") { + hull() for (y = [0, 12]) { + translate([1.27, 1.27 + 2.54 * y, 0.5]) { + cylinder(r=1, h=1.1, center=true, $fn=8); + } + } + hull() { + for (y = [0, 11]) { + translate([1.27 + 2.54, 1.27 + 2.54 * y, 0.5]) { + cylinder(r=1, h=1.1, center=true, $fn=8); + } + } + for (y = [0, 10]) { + translate([12.72 - 1.27 - 2.54, 1.27 + 2.54 * y, 0.5]) { + cylinder(r=1, h=1.1, center=true, $fn=8); + } + } + } + hull() for (y = [0, 12]) { + translate([12.72 - 1.27, 1.27 + 2.54 * y, 0.5]) { + cylinder(r=1, h=1.1, center=true, $fn=8); + } + } + hull() { + translate([1.27, 1.27 + 2.54 * 12, 0.5]) { + cylinder(r=1, h=1.1, center=true, $fn=8); + } + translate([12.72 - 1.27, 1.27 + 2.54 * 12, 0.5]) { + cylinder(r=1, h=1.1, center=true, $fn=8); + } + } + } + color("Gold") { + for (y = [0, 1, 2, 3, 4, 5, 6, 7, 10, 11]) { + translate([1.27, 1.27 + 2.54 * y, 0.5]) { + cylinder(r=0.8, h=1.2, center=true, $fn=8); + } + } + for (y = [0, 1, 2, 3, 4, 5, 6, 7, 10, 11]) { + translate([1.27 + 2.54, 1.27 + 2.54 * y, 0.5]) { + cylinder(r=0.8, h=1.2, center=true, $fn=8); + } + } + for (y = [0, 1, 2, 3, 4, 5, 6, 7, 10]) { + translate([12.72 - 1.27 - 2.54, 1.27 + 2.54 * y, 0.5]) { + cylinder(r=0.8, h=1.2, center=true, $fn=8); + } + } + for (y = [0, 1, 2, 3, 4, 5, 6, 7, 11]) { + translate([12.72 - 1.27, 1.27 + 2.54 * y, 0.5]) { + cylinder(r=0.8, h=1.2, center=true, $fn=8); + } + } + } + } + color("Gold") for (y = [0, 1, 2, 3, 4, 5, 6, 7, 10, 11]) { + translate([1.27, 1.27 + 2.54 * y, 0.5]) { + cylinder(r=0.4, h=1.4, center=true, $fn=8); + } + translate([1.27 + 2.54, 1.27 + 2.54 * y, 0.5]) { + cylinder(r=0.4, h=1.4, center=true, $fn=8); + } + } + color("Gold") for (y = [0, 1, 2, 3, 4, 5, 6, 7, 10]) { + translate([12.72 - 1.27 - 2.54, 1.27 + 2.54 * y, 0.5]) { + cylinder(r=0.4, h=1.4, center=true, $fn=8); + } + } + color("Gold") for (y = [0, 1, 2, 3, 4, 5, 6, 7, 11]) { + translate([12.72 - 1.27, 1.27 + 2.54 * y, 0.5]) { + cylinder(r=0.4, h=1.4, center=true, $fn=8); + } + } + } + for (y = [0, 1, 2, 3, 4, 5, 6, 7, 10, 11]) { + translate([1.27, 1.27 + 2.54 * y, 1]) { + rotate([0, 180, 0]) short_pin(); + } + translate([1.27 + 2.54, 1.27 + 2.54 * y, 1]) { + rotate([0, 180, 0]) short_pin(); + } + } + for (y = [0, 1, 2, 3, 4, 5, 6, 7, 11]) { + translate([12.72 - 1.27, 1.27 + 2.54 * y, 1]) { + rotate([0, 180, 0]) short_pin(); + } + } + for (y = [0, 1, 2, 3, 4, 5, 6, 7, 10]) { + translate([12.72 - 1.27 - 2.54, 1.27 + 2.54 * y, 1]) { + rotate([0, 180, 0]) short_pin(); + } + } + translate([1.8, 22.8, -3]) rotate([0, 90, 0]) capacitor(); +} + + +arduino_pro_mini(); +arduino_pro_mini_goldpins(); +translate([2.54, 0, -1.75]) board(); +translate([17.72, 33 - 2.54, -1]) rotate([0, 180, 90]) jumper(); +for (y=[0:7]) { + translate([0, y * 2.54, -2.1]) rotate([0, 180, -90]) SG90_plug(); +} +for (y=[1:4]) { + translate([7.62 * 2 + 2.54, y * 2.54, -2.1]) rotate([0, 180, 90]) SG90_plug(); +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/scad/body.scad Mon Sep 29 21:33:19 2014 +0200 @@ -0,0 +1,48 @@ +module body() { + color("AliceBlue", 0.5) union() { + difference() { + hull() { + translate([20, 20, 0]) cylinder(r=5, h=5, $fn=16); + translate([-20, 20, 0]) cylinder(r=5, h=5, $fn=16); + translate([20, -20, 0]) cylinder(r=5, h=5, $fn=16); + translate([-20, -20, 0]) cylinder(r=5, h=5, $fn=16); + } + translate([0, 0, 1]) hull() { + translate([19, 19, 0]) cylinder(r=5, h=5, $fn=16); + translate([-19, 19, 0]) cylinder(r=5, h=5, $fn=16); + translate([19, -19, 0]) cylinder(r=5, h=5, $fn=16); + translate([-19, -19, 0]) cylinder(r=5, h=5, $fn=16); + } + translate([20, 20, -1]) cylinder(r=2.2, h=8, $fn=8); + translate([-20, 20, -1]) cylinder(r=2.2, h=8, $fn=8); + translate([20, -20, -1]) cylinder(r=2.2, h=8, $fn=8); + translate([-20, -20, -1]) cylinder(r=2.2, h=8, $fn=8); + translate([13.6, 13.6, -1]) cylinder(r=0.7, h=8, $fn=8); + translate([13.6, -13.6, -1]) cylinder(r=0.7, h=8, $fn=8); + translate([-13.6, 13.6, -1]) cylinder(r=0.7, h=8, $fn=8); + translate([-13.6, -13.6, -1]) cylinder(r=0.7, h=8, $fn=8); + translate([9.4, 9.4, -1]) cylinder(r=0.7, h=8, $fn=8); + translate([-9.4, 9.4, -1]) cylinder(r=0.7, h=8, $fn=8); + translate([9.4, -9.4, -1]) cylinder(r=0.7, h=8, $fn=8); + translate([-9.4, -9.4, -1]) cylinder(r=0.7, h=8, $fn=8); + } + } + color("AliceBlue", 0.5) union() { + translate([0, 0, 5 + $explode]) difference() { + hull() { + translate([20, 20, 0]) cylinder(r=5, h=40, $fn=16); + translate([-20, 20, 0]) cylinder(r=5, h=40, $fn=16); + translate([20, -20, 0]) cylinder(r=5, h=40, $fn=16); + translate([-20, -20, 0]) cylinder(r=5, h=40, $fn=16); + } + translate([0, 0, -1]) hull() { + translate([19, 19, 0]) cylinder(r=5, h=40, $fn=16); + translate([-19, 19, 0]) cylinder(r=5, h=40, $fn=16); + translate([19, -19, 0]) cylinder(r=5, h=40, $fn=16); + translate([-19, -19, 0]) cylinder(r=5, h=40, $fn=16); + } + } + } +} + +body();
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/scad/leg.scad Mon Sep 29 21:33:19 2014 +0200 @@ -0,0 +1,30 @@ +use <sg90.scad> + +module leg(hip=0, knee=0, ankle=0) { + rotate(-90) { + rotate(90) SG90_single_horn(); + translate([0, 0, $explode]) SG90_horn_screw(); + translate([0, 6, 7 - $explode]) rotate([0, 180, 0]) SG90_horn_screw(); + translate([0, 12, 7 - $explode]) rotate([0, 180, 0]) SG90_horn_screw(); + translate([0, 0, -$explode]) rotate(hip) { + SG90(); + translate([-3 - $explode, -20.5, -15]) rotate([-90, 0, 90]) SG90_double_horn(); + translate([-4.5 - $explode, -39.5, -15]) rotate([-90, 0, 90]) { + translate([0, 0, $explode]) SG90_single_horn(); + translate([0, 0, $explode * 2]) SG90_horn_screw(); + translate([0, 0, -$explode]) { + translate([8, 0, 5]) rotate([0, 180, 0]) SG90_horn_screw(); + translate([12, 0, 5]) rotate([0, 180, 0]) SG90_horn_screw(); + } + rotate(knee) { + rotate(180) SG90(); + translate([-10.5 - $explode, 20.5, -11]) rotate([90, 0, 90]) { + SG90_double_horn(); + } + } + } + } + } +} + +leg(0, 0);
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/scad/robot.scad Mon Sep 29 21:33:19 2014 +0200 @@ -0,0 +1,22 @@ +use <leg.scad> +use <body.scad> + +module robot() { + translate([0, 0, 70]) union() { + translate([20, 20, -5.1 - $explode]) rotate(-135) { + leg(0, 0, 0, $explode); + } + translate([-20, -20, -5.1 - $explode]) rotate(45) { + leg(0, 0, 0, $explode); + } + translate([20, -20, -5.1 - $explode]) rotate(135) mirror([0, 1, 0]) { + leg(0, 0, 0, $explode); + } + translate([-20, 20, -5.1 - $explode]) rotate(-45) mirror([0, 1, 0]) { + leg(0, 0, 0, $explode); + } + translate([0, 0, $explode]) body($explode); + } +} + +rotate($t * 180) robot($explode=10 + 10 * sin($t * 360));
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/scad/sg90.scad Mon Sep 29 21:33:19 2014 +0200 @@ -0,0 +1,121 @@ +module SG90() { + servo_height = 22.6; + servo_width = 12.2; + servo_depth = 22.8; + servo_ear_depth = 4.8; + servo_big_tip_r = 6.05; + + translate([-6.0, -16.9, -servo_height - 5.8 - 1]) union() { + color("MediumSlateBlue", 0.75) union () { + cube([servo_width, servo_depth, servo_height]); + translate([0, -4.8, 17.6]) { + difference () { + cube([12.0, 32.3, 2.4]); + translate([6.0, 1.5, -0.1]) cylinder(r=2, h=2.6, $fn=10); + translate([6.0, 30.8, -0.1]) cylinder(r=2, h=2.6, $fn=10); + } + } + translate([6.0, 16.9, servo_height]) { + cylinder(r=servo_big_tip_r, h=5.8, $fn=20); + } + translate([6.0, 16.9 - servo_big_tip_r, servo_height]) { + cylinder(r=2.75, h=5.8, $fn=10); + } + } + color("Snow") translate([6.0, 16.9, servo_height + 5.8]) difference() { + cylinder(r=2.275, h=3.9, $fn=6); + cylinder(r=0.8, h=5, $fn=10); + } + } + translate([1, -10, -25]) rotate([0, 90, 90]) { + color("Orange") translate([1.27, 0, 12]) cylinder(r1=0.75, r2=0, h=20); + color("Red") translate([1.27, 1, 12]) cylinder(r1=0.75, r2=0, h=20); + color("Brown") translate([1.27, 2, 12]) cylinder(r1=0.75, r2=0, h=20); + } +} + +module _SG90_horn_arm() { + difference() { + translate([13.8, 0, 3.1]) { + cylinder(r=1.85, h=1.3, $fn=10); + translate([0,-2,0]) rotate([0,0,94]) { + cube([4, 13.8, 1.3]); + } + translate([0,-2,0]) rotate([0,0,86]) { + cube([4, 13.8, 1.3]); + } + } + for(i=[0:5]) { + translate([13.8 - i * 2,0,0]) { + cylinder(r=0.6, h=8, $fn=8); + } + } + } +} + +module SG90_single_horn(angle) { + rotate(angle) color("Snow") { + difference() { + union() { + cylinder(r=3.3, h=4.4, $fn=20); + _SG90_horn_arm(); + } + translate([0,0,-1]) { + cylinder(r=2.275, h=3.2, $fn=6); + cylinder(r=1, h=8, $fn=10); + translate([0, 0, 4.4]) cylinder(r=2.35, h=2, $fn=10); + } + } + } +} + +module SG90_double_horn(angle) { + rotate(angle) color("Snow") { + difference() { + union() { + cylinder(r=3.3, h=4.4, $fn=20); + _SG90_horn_arm(); + rotate(180) _SG90_horn_arm(); + } + translate([0,0,-1]) { + cylinder(r=2.275, h=3.2, $fn=6); + cylinder(r=1, h=8, $fn=10); + translate([0, 0, 4.4]) cylinder(r=2.35, h=2, $fn=10); + } + } + } +} + +module SG90_horn_screw() { + color("DarkGray") union() { + translate([0, 0, 3.4]) difference() { + union() { + cylinder(r=1.4, h=0.9, $fn=6); + translate([0, 0, -3.4]) cylinder(r=0.8, h=4, $fn=8); + } + translate([-0.25, -2, 0.4]) cube([0.5, 4, 1]); + } + } +} + +module SG90_plug() { + color("Orange") translate([1.27, 1.27, 12]) cylinder(r1=0.75, r2=0, h=20); + color("Red") translate([1.27, 1.27 + 2.54, 12]) cylinder(r1=0.75, r2=0, h=20); + color("Brown") translate([1.27, 1.27 + 2.54 * 2, 12]) cylinder(r1=0.75, r2=0, h=20); + color("DimGray") difference() { + cube([2.54, 2.54 * 3, 12]); + translate([-1, -1, -1]) cube([1.25, 2.54 * 3 + 2, 7]); + rotate(45) cube([1, 2, 12], center=true); + translate([0, 2.54*3, 0]) rotate(-45) cube([1, 2, 12], center=true); + for (y = [0:2]) { + translate([1.27, 1.27 + y * 2.54, -1]) cylinder(r=0.5, h=12); + } + } +} + + +SG90(); +SG90_double_horn(90); +translate([0, 0, 10]) SG90_single_horn(90); +translate([0, 0, 20]) SG90_horn_screw(); +translate([0, -20, 10]) SG90_plug();
