Blog: Bird photos

This commit is contained in:
Pascal Engélibert 2025-02-06 13:47:13 +01:00
commit 961fcac52c
8 changed files with 580 additions and 0 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 78 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 84 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 83 KiB

View file

@ -0,0 +1,64 @@
+++
title = "Timelapse et oiseaux de l'espace"
date = 2025-02-06
description = "Un déclencheur photo avec capteur de présence"
insert_anchor_links = "left"
[taxonomies]
tags = ["Arduino", "électronique", "photo"]
+++
## Un rouge-gorge dans les étoiles
Rouge-gorges, moineaux, merles et mésanges visitent toute la journée le jardin mais s'envolent à la vue d'hominidés.
Comment donc, sans téléobjectif, les prendre en photo ?
En fabriquant un déclencheur doté d'un capteur de distance infrarouge !
![Un rouge-gorge, tête vers le haut, posé sur le bord d'une table de jardin en bois, regarde de travers un petit récipient plat et rond devant lui, à côté duquel sont dispersées quelques graines. Dans le récipient on voit des étoiles et des nébuleuses.](dream1.webp)
![Le rouge-gorge se penche vers le récipient, en restant à distance. On voit un manchot dans les étoiles, une aile dépassant du bord du récipient.](dream2.webp)
![Le rouge-gorge s'est retourné dos à la caméra. Il est juste devant le récipient. Deux manchots sont sortis du récipient, qui laisse toujours voir un ciel étoilé. L'un a sauté du bord de la table, les ailes et les pattes déployées. L'autre s'apprête à le suivre, posé au bord, regardant vers le sol.](dream3.webp)
[Davantage de photos en haute résolution sont disponibles ici.](/img/birds/)
## Humble timelapse
Il y a aussi un mode périodique, pour faire un timelapse.
Dans la vidéo la luminosité varie parce que j'avais oublié de désactiver la balance automatique.
<iframe title="Timelapse - trees and sky - 2020-10-31" width="560" height="315" src="https://flim.txmn.tk/videos/embed/3acae4de-2669-4b48-867d-41a980bfce9c" frameborder="0" allowfullscreen="" sandbox="allow-same-origin allow-scripts allow-popups allow-forms"></iframe>
## Le déclencheur
Mon appareil photo (Nikon D3000) possède un récepteur infrarouge, pour lequel je n'ai pas de télécommande.
Heureusement quelqu'un a publié un code Arduino répliquant le signal de la télécommande: [_Nikon Remote Emulator_ by Gough Lui](https://goughlui.com/2013/12/06/teardown-and-project-clone-nikon-ml-l3-ir-remote-and-emulation/)
Il suffit d'un microcontrôleur et d'une LED infrarouge (récupérée d'une vieille télécommande TV).
Le détecteur d'oiseau est un capteur de distance infrarouge GP2D12, capable d'évaluer (très grossièrement) la distance sur 20 à 80cm.
Il est perché sur un bras articulé à distance de l'appareil photo (pour pouvoir régler la focale et ne pas effrayer les oiseaux).
Un interrupteur pour choisir le mode (capteur ou intervalle fixe), et un potentiomètre pour choisir la valeur (distance pour le mode capteur, durée pour le mode intervalle).
Il faut aussi déclencher l'appareil toutes les quelques minutes pour l'empêcher de se mettre en veille (ce qui demanderait un rallumage manuel).
Le boîtier est conçu pour une Arduino Micro mais un ATtiny402 suffirait largement.
Le bras articulé se fixe sur le trépied de l'appareil photo.
![Bras articulé fait de doubles tiges de métal. À une extrémité, un serrage pour fixer le tout au trépied. Entre les deux segments, une jointure en genou. Sur le deuxième segment, le boîtier contenant l'Arduino, la LED, l'interrupteur et le potentiomètre. Au bout, le capteur infrarouge relié par trois fils au boîtier.](remote.webp)
* [nikon_ir_trigger.ino](nikon_ir_trigger.ino) (programme Arduino)
* [timelapser.scad](timelapser.scad) (modèle 3D [OpenSCAD](https://openscad.org/), pour impression 3D)
* [pitch.scad](pitch.scad) (pas de vis et support de boulon)
## Crédits
Le montage avec le rouge-gorge utilise deux images dont je ne suis pas l'auteur&nbsp;:
* _Adelie Penguin (Pygoscelis adeliae) group on iceberg, Antarctic Peninsula, Antarctica_, image partagée partout sur Internet sans attribution, dont je ne trouve pas la publication originale.
* [Westerlund 2, photographed by the Hubble Space Telescope (heic1509a)](https://esahubble.org/images/heic1509a/)
Images retouchées avec Gimp, optimisées avec YOGA Image Optimizer.
Aucun animal n'a subi de violence pendant les séances photo.
Les participants n'ont pas signé de droit à l'image mais ont été rémunérés en graines.

View file

@ -0,0 +1,73 @@
#define PIN_TRIGGER 13 // IR LED
#define PIN_SENSOR A0 // Distance sensor (GP2D12)
#define PIN_POT A1 // Parameter potentiometer
#define PIN_SWITCH 8 // Mode switch
#define INTERVAL 1000
#define N_MEASURE 4
#define PREVENT_SLEEP_INTERVAL 270000
char count;
unsigned long prevent_sleep = 0;
unsigned long last_shot = 0;
void trigger() {
// Nikon Remote Emulator by Gough Lui
// https://goughlui.com/2013/12/06/teardown-and-project-clone-nikon-ml-l3-ir-remote-and-emulation/
count = 0;
while(count < 3) {
tone(PIN_TRIGGER, 38000);
delay(2);
noTone(PIN_TRIGGER);
delay(28);
tone(PIN_TRIGGER, 38000);
delayMicroseconds(200);
noTone(PIN_TRIGGER);
delayMicroseconds(1500);
tone(PIN_TRIGGER, 38000);
delayMicroseconds(200);
noTone(PIN_TRIGGER);
delayMicroseconds(3300);
tone(PIN_TRIGGER, 38000);
delayMicroseconds(200);
noTone(PIN_TRIGGER);
delayMicroseconds(100);
delay(63);
count ++;
}
prevent_sleep = millis() + PREVENT_SLEEP_INTERVAL;
delay(INTERVAL);
}
int measure() {
int result = 0;
for(char i=0; i<N_MEASURE; i++) {
result += analogRead(PIN_SENSOR);
}
return result / N_MEASURE;
}
void setup() {
pinMode(PIN_SWITCH, INPUT_PULLUP);
pinMode(PIN_TRIGGER, OUTPUT);
digitalWrite(PIN_TRIGGER, LOW);
}
void loop() {
if(digitalRead(PIN_SWITCH)) { // Sensor mode
unsigned int threshold = map(analogRead(PIN_POT), 0, 1023, 81, 532);
if(measure() > threshold) {
trigger();
}
else if(millis() > prevent_sleep) {
trigger();
}
} else { // Interval mode
unsigned long interval = map(analogRead(PIN_POT), 0, 1023, 2000, 300000);
if(millis() > last_shot + interval) {
last_shot = millis();
trigger();
}
}
}

View file

@ -0,0 +1,110 @@
/*
* CopyLeft 2017-2022 Pascal Engélibert
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
// Ideal values but may increase depending on printer/slicer settings
// Please print tests to fine tune this parameter
M3_RAY = 1.725; // M3 bolt ray (diameter=3mm) Ideal=1.5
// Functions are accessible outside scope, not variables
function M3_RAY() = M3_RAY;
module hexagone(l,h) {
a = l/tan(60);
union() {
rotate([0,0,0]) cube([l,a,h],center=true);
rotate([0,0,60]) cube([l,a,h],center=true);
rotate([0,0,120]) cube([l,a,h],center=true);
}
}
// added h:0.6 w:0.25
// b:add bottom nut support
// s:bottom support height
module pitch_m2_5(b=0,s=0) {
translate([0,0,(b+s)/2]) difference() {
hexagone(7.25,b+s);
cylinder(h=1+b+s,r=1.375,center=true,$fn=20);
if(s>0) {
translate([0,0,-b]) hexagone(5.25,b+s);
translate([-2.625,0,-(b+s)/2-b]) cube([5.25,5.25,b+s]);
}
}
translate([0,0,1.8+b+s]) difference() {
hexagone(7.25,3.6);
cylinder(h=4.6,r=1.375,center=true,$fn=20);
translate([0,0,-1]) hexagone(5.25,3.6);
translate([-2.625,0,-2.8]) cube([5.25,5.25,3.6]);
}
}
// b:add bottom nut support
// s:bottom support height
// h:head support additionnal thickness
// w:side additionnal thickness
module pitch_m3(b=0,s=0,h=0,w=0) {
translate([0,0,(b+s)/2]) difference() {
hexagone(7.75+w,b+s);
cylinder(h=1+b+s,r=M3_RAY,center=true,$fn=20);
if(s>0) {
translate([0,0,-b]) hexagone(5.75,b+s);
translate([-2.875,0,-(b+s)/2-b]) cube([5.75,5.75,b+s]);
}
}
translate([0,0,2+b+s+h/2]) difference() {
hexagone(7.75+w,4+h);
cylinder(h=5+h,r=M3_RAY,center=true,$fn=20);
translate([0,0,-1]) hexagone(5.75,4);
translate([-2.875,0,-3]) cube([5.75,5.75,4]);
}
}
module pitch_inv_m3(y=0, z1=0, z2=0, hp=0) {
translate([0,0,2-hp/2]) hexagone(5.75, 4+hp);
translate([-3,0,-hp]) cube([6, y, 4+hp]);
translate([0,0,-z2-hp]) cylinder(r=M3_RAY, h=z1+4+z2+hp, $fn=20);
}
module simple_pitch_m3(th=1, h1=1, h2=1) {
difference() {
translate([0, 0, 2+h1/2-h2/2]) hexagone(7+th, 4+h1+h2);
pitch_inv_m3(6+th, h1+1, h2+1);
}
}
// a:rod radius
// t:thickness
module rod_pitch_m3(a, t=2, center=true) {
translate([0,0,center?0:4.375]) difference() {
union() {
cylinder(h=8.75, r=a+t, center=true, $fn=60);
rotate([0,90,0]) pitch_m3(a+t,0,1,1);
}
cylinder(h=9, r=a, center=true, $fn=60);
rotate([0,90,0]) cylinder(h=a+t+1, r=1.625, $fn=20);
}
}
module side_pitch_m3(th=1.2, h1=1, h2=2) {
difference() {
translate([0,0,2+h1/2-h2/2]) hexagone(7+th, 4+h1+h2);
pitch_inv_m3(6+th, h1+1, h2+1, h1);
}
}
//rod_pitch_m3(3);
side_pitch_m3();

Binary file not shown.

After

Width:  |  Height:  |  Size: 70 KiB

View file

@ -0,0 +1,333 @@
use<pitch.scad>;
module Box(
in_l = 50,
in_w = 45,
in_h = 40,
wall_th = 2,
pot_d = 7.7,
pot_x = 36,
pot_y = 20,
pot_mark_dist = 8,
pot_mark_d = 3,
sw_w = 6,
sw_l = 8.2,
sw_joint_dist = 15,
sw_joint_d = 3,
sw_joint_depth = 1,
sw_screw_dist = 8,
sw_screw_d = 3.6,
sw_x = 12,
sw_y = 25,
ino_h = 26,
ino_l = 47, // Length of Arduino itself
ino_w = 18, // Width of Arduino itself
ino_hold1_l = 2.25, // USB side
ino_hold1_w = 4,
ino_hold2_l = 2.25, // Other side
ino_hold2_w = 2,
ino_hold3_m = 1, // Inner side
ino_hold3_h = 3,
ino_hold3_l = 4,
ino_hold3_th = 2,
ino_hold3_supp = 5,
ino_x = 0, // From USB side
usb_y = 3, // From ino_h
usb_w = 11,
usb_h = 7,
usb_y = 3, // Distance between bottom of Arduino PCB and center of USB port
sensor_w = 10,
sensor_h = 7,
sensor_x = 18,
sensor_y = 6,
ir_d = 8,
ir_x = 15,
ir_y = 7,
ir_hold_dist = 17,
ir_hold_small_h = 2.2,
ir_hold_small_d = 7,
ir_hold_offset = -6,
lid_screw_d = 4,
lid_screw_dist_side = 16,
lid_screw_dist_top = 5,
arm_joint_d = 6,
arm_joint_th = 5,
arm_joint_margin = 4,
arm_joint_dist = 8
) {
difference() {
cube([in_l+2*wall_th, in_w+2*wall_th, in_h+wall_th]);
// Inside
translate([wall_th, wall_th, wall_th]) cube([in_l, in_w, in_h+wall_th]);
// Potentiometer
translate([wall_th+pot_x, 0, wall_th+pot_y]) rotate([-90,0,0])
cylinder(d=pot_d, h=wall_th, $fn=60);
translate([wall_th+pot_x+pot_mark_dist, 0, wall_th+pot_y]) rotate([-90,0,0])
cylinder(d=pot_mark_d, h=wall_th, $fn=60);
translate([wall_th+pot_x+-pot_mark_dist, 0, wall_th+pot_y]) rotate([-90,0,0])
cylinder(d=pot_mark_d, h=wall_th, $fn=60);
// Switch
translate([wall_th+sw_x, 0, wall_th+sw_y]) union() {
translate([-sw_l/2, 0, -sw_w/2]) cube([sw_l, wall_th, sw_w]);
translate([-sw_joint_dist/2, wall_th-sw_joint_depth, 0]) rotate([-90,0,0])
cylinder(d=sw_joint_d, h=wall_th, $fn=60);
translate([sw_joint_dist/2, wall_th-sw_joint_depth, 0]) rotate([-90,0,0])
cylinder(d=sw_joint_d, h=wall_th, $fn=60);
translate([0, 0, sw_screw_dist]) rotate([-90,0,0])
cylinder(d=sw_screw_d, h=wall_th, $fn=60);
};
// USB
translate([wall_th+in_l, wall_th+in_w-ino_w/2-usb_w/2, wall_th+ino_h+usb_y-usb_h/2])
cube([wall_th, usb_w, usb_h]);
// Sensor cable
translate([wall_th+in_l, wall_th+sensor_x-sensor_w/2, wall_th+sensor_y-sensor_h/2])
cube([wall_th, sensor_w, sensor_h]);
// IR LED
translate([0, wall_th+ir_x, wall_th+ir_y])
rotate([0,90,0]) cylinder(d=ir_d, h=wall_th, $fn=60);
translate([wall_th+ir_hold_dist, wall_th+ir_x+ir_hold_offset, 0])
rotate([0,0,30]) pitch_inv_m3();
// Lid screws
translate([0, wall_th+lid_screw_dist_side, wall_th+in_h-lid_screw_dist_top])
rotate([0,90,0]) cylinder(d=lid_screw_d, h=wall_th, $fn=60);
translate([wall_th+in_l, wall_th+lid_screw_dist_side, wall_th+in_h-lid_screw_dist_top])
rotate([0,90,0]) cylinder(d=lid_screw_d, h=wall_th, $fn=60);
}
// Arduino holder
translate([wall_th, wall_th+in_w-ino_hold2_w, wall_th])
cube([ino_x+ino_hold2_l, ino_hold2_w, ino_h]);
translate([wall_th, wall_th+in_w-ino_w, wall_th])
cube([ino_x+ino_hold2_l, ino_hold2_w, ino_h]);
translate([wall_th+in_l-ino_hold1_l, wall_th+in_w-ino_hold1_w, wall_th])
cube([ino_x+ino_hold1_l, ino_hold1_w, ino_h]);
translate([wall_th+in_l-ino_hold1_l, wall_th+in_w-ino_w, wall_th])
cube([ino_x+ino_hold1_l, ino_hold1_w, ino_h]);
translate([wall_th, wall_th+in_w-ino_w-ino_hold3_m-ino_hold3_th, wall_th+ino_h])
hull() {
cube([ino_hold3_l, ino_hold3_th, ino_hold3_h]);
translate([-wall_th, 0, -ino_hold3_supp])
cube([wall_th, ino_hold3_th, ino_hold3_supp]);
};
translate([wall_th+in_l-ino_hold3_l, wall_th+in_w-ino_w-ino_hold3_m-ino_hold3_th, wall_th+ino_h])
hull() {
cube([ino_hold3_l, ino_hold3_th, ino_hold3_h]);
translate([ino_hold3_l, 0, -ino_hold3_supp])
cube([wall_th, ino_hold3_th, ino_hold3_supp]);
};
// IR LED holder
translate([wall_th+ir_hold_dist, wall_th+ir_x+ir_hold_offset, wall_th]) rotate([0,0,-90])
pitch_m3(s=ir_y-4-ir_hold_small_h);
translate([wall_th+ir_hold_dist, wall_th+ir_x+ir_hold_offset, wall_th+ir_y-ir_hold_small_h])
difference() {
cylinder(d=ir_hold_small_d, h=ir_hold_small_h, $fn=60);
cylinder(r=M3_RAY(), h=ir_hold_small_h, $fn=20);
};
// Arm joint
translate([wall_th+in_l/2, 2*wall_th+in_w, 0]) difference() {
union() {
translate([-arm_joint_d/2-arm_joint_margin, 0, 0])
cube([arm_joint_d+2*arm_joint_margin, arm_joint_dist, arm_joint_th]);
translate([0, arm_joint_dist, 0])
cylinder(d=arm_joint_d+2*arm_joint_margin, h=arm_joint_th, $fn=60);
}
translate([0, arm_joint_dist, 0])
cylinder(d=arm_joint_d, h=arm_joint_th, $fn=60);
};
//color("#ff000066") translate([wall_th+sw_x, wall_th+0.4, wall_th+sw_y]) rotate([0,0,180]) SwitchAttach();
}
// TODO ajouter supports Arduino
module Lid(
in_l = 50,
in_w = 45,
in_h = 40,
wall_th = 2,
ino_h = 26,
ino_l = 47, // Length of Arduino itself
ino_w = 18, // Width of Arduino itself
ino_hold_h = 13,
ino_hold1_x = 9,
ino_hold1_l = 2,
ino_hold1_y = 29.5,
ino_hold1_w = 11.5,
ino_hold2_x = 37.5,
ino_hold2_l = 2,
ino_hold2_y = 37,
ino_hold2_w = 4,
border_h = 1.6,
border_margin = 0.8,
led1_x = 17,
led1_y = 38,
led1_d = 3,
led2_x = 37,
led2_y = 33,
led2_d = 3,
led3_x = 39,
led3_y = 33,
led3_d = 3,
reset_x = 47,
reset_y = 35,
reset_d = 4.5,
lid_screw_d = 4,
lid_screw_dist_side = 16,
lid_screw_dist_top = 5.5,
lid_screw_margin = 2.5,
lid_screw_th = 1.5
) {
difference() {
union() {
cube([in_l+2*wall_th, in_w+2*wall_th, wall_th]);
translate([wall_th+border_margin, wall_th+border_margin, wall_th]) difference() {
cube([in_l-2*border_margin, in_w-2*border_margin, border_h]);
translate([wall_th, wall_th, 0])
cube([in_l-2*border_margin-2*wall_th, in_w-2*border_margin-2*wall_th, border_h]);
}
}
translate([led1_x, led1_y, 0])
cylinder(d=led1_d, h=wall_th+border_h, $fn=40);
translate([led2_x, led2_y, 0])
cylinder(d=led2_d, h=wall_th+border_h, $fn=40);
translate([led3_x, led3_y, 0])
cylinder(d=led3_d, h=wall_th+border_h, $fn=40);
translate([reset_x, reset_y, 0])
cylinder(d=reset_d, h=wall_th+border_h, $fn=40);
}
translate([wall_th+border_margin, wall_th+lid_screw_dist_side, wall_th]) difference() {
union() {
translate([0, -lid_screw_d/2-lid_screw_margin, 0])
cube([lid_screw_th, lid_screw_d+2*lid_screw_margin, lid_screw_dist_top]);
translate([0, 0, lid_screw_dist_top])
rotate([0,90,0])
cylinder(d=lid_screw_d+2*lid_screw_margin, h=lid_screw_th, $fn=60);
translate([lid_screw_th,0,lid_screw_dist_top]) rotate([90,0,0]) rotate([0,90,0])
pitch_m3();
}
translate([0, 0, lid_screw_dist_top])
rotate([0,90,0]) cylinder(d=lid_screw_d, h=wall_th, $fn=60);
}
translate([in_l-border_margin+wall_th-lid_screw_th, wall_th+lid_screw_dist_side, wall_th]) difference() {
union() {
translate([0, -lid_screw_d/2-lid_screw_margin, 0])
cube([lid_screw_th, lid_screw_d+2*lid_screw_margin, lid_screw_dist_top]);
translate([0, 0, lid_screw_dist_top])
rotate([0,90,0])
cylinder(d=lid_screw_d+2*lid_screw_margin, h=lid_screw_th, $fn=60);
translate([0,0,lid_screw_dist_top]) rotate([90,0,0]) rotate([0,-90,0])
pitch_m3();
}
translate([0, 0, lid_screw_dist_top])
rotate([0,90,0]) cylinder(d=lid_screw_d, h=wall_th, $fn=60);
}
translate([wall_th+ino_hold1_x, wall_th+ino_hold1_y, wall_th])
cube([ino_hold1_l, ino_hold1_w, ino_hold_h]);
translate([wall_th+ino_hold2_x, wall_th+ino_hold2_y, wall_th])
cube([ino_hold2_l, ino_hold2_w, ino_hold_h]);
}
module SwitchAttach(
joint_d = 1.5,
joint_dist = 15,
joint_h = 2,
screw_dist = 8,
screw_d = 3.6,
arm_joint_in_w = 1,
arm_joint_out_w = 2,
arm_joint_bottom_w = 2.6,
arm_screw_in_w = 3,
arm_screw_out_w = 5,
arm_th = 2,
) {
translate([-joint_dist/2, arm_th, 0]) rotate([-90,0,0])
cylinder(d=joint_d, h=joint_h, $fn=60);
translate([joint_dist/2, arm_th, 0]) rotate([-90,0,0])
cylinder(d=joint_d, h=joint_h, $fn=60);
difference() {
translate([-joint_dist/2-arm_joint_out_w, 0, screw_dist-arm_screw_in_w])
cube([joint_dist+2*arm_joint_out_w, arm_th, arm_screw_in_w+arm_screw_out_w]);
translate([0, 0, screw_dist]) rotate([-90,0,0])
cylinder(d=screw_d, h=arm_th, $fn=60);
};
translate([-joint_dist/2-arm_joint_out_w, 0, -arm_joint_bottom_w])
cube([arm_joint_out_w+arm_joint_in_w, arm_th, arm_joint_bottom_w+screw_dist]);
translate([joint_dist/2-arm_joint_in_w, 0, -arm_joint_bottom_w])
cube([arm_joint_out_w+arm_joint_in_w, arm_th, arm_joint_bottom_w+screw_dist]);
}
module ArmJoint(
d = 19,
rod_d = 3.8,
rod_dist = 8.5,
rod_z = 0.3,
th = 4.8,
hole_d = 4,
) {
difference() {
cylinder(d=d, h=th, $fn=80);
cylinder(d=hole_d, h=th+1, $fn=40);
translate([-rod_dist/2, -d/2, rod_z+th])
rotate([-90, 0, 0])
cylinder(d=rod_d, h=d, $fn=40);
translate([rod_dist/2, -d/2, rod_z+th])
rotate([-90, 0, 0])
cylinder(d=rod_d, h=d, $fn=40);
}
}
module RodSupport(
ear_l = 15,
ear_th = 4,
out_d = 32,
rod_d = 25.5,
rod_offset = 0.5,
screw_d = 4,
screw_dist = 9,
w = 10,
) {
difference() {
union() {
cylinder(d=out_d, h=w, $fn=80);
hull() {
translate([out_d/2+screw_dist, 0, w/2])
rotate([-90, 0, 0])
cylinder(d=w, h=ear_th, $fn=60);
translate([-out_d/2-screw_dist, 0, w/2])
rotate([-90, 0, 0])
cylinder(d=w, h=ear_th, $fn=60);
}
//translate([-out_d/2-ear_l, 0, 0]) cube([out_d+2*ear_l, ear_th, w]);
}
// Ears
translate([-out_d/2, -out_d, 0]) cube([out_d, out_d, w]);
// Rod
translate([0, -rod_offset, 0]) cylinder(d=rod_d, h=w, $fn=80);
// Screws
translate([out_d/2+screw_dist, 0, w/2])
rotate([-90, 0, 0])
cylinder(d=screw_d, h=ear_th, $fn=40);
translate([-out_d/2-screw_dist, 0, w/2])
rotate([-90, 0, 0])
cylinder(d=screw_d, h=ear_th, $fn=40);
}
}
//Box();
//rotate([90,0,0]) SwitchAttach();
//Lid();
ArmJoint();
//RodSupport();