-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathPyFlyCage.scad
executable file
·709 lines (604 loc) · 28.6 KB
/
PyFlyCage.scad
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
// PyFly Cage design
// written in OpenSCAD
// Camera flex cable: https://smile.amazon.com/gp/product/B0716TB6X3/ref=oh_aui_detailpage_o00_s00?ie=UTF8&psc=1
//
//
// Written: 9/10/2017
// Rev.: 0.01
// By: Robert S. Rau
// Updated: 9/30/2017
// Rev.: 0.02
// By: Robert S. Rau
// Changes: more cutouts for connectors and wire
//
// Updated: 10/1/2017
// Rev.: 0.03
// By: Robert S. Rau
// Changes: added camera, more room for GPS antenna, changed left/right logic so GPS antenna slide-in would work, bigger width for USB connectors on Zero
//
// Updated: 10/3/2017
// Rev.: 0.04
// By: Robert S. Rau
// Changes: added extra width to camera so it can be removed, added wire channel so sliding cage together doesn't crush camera flat cable. Added champhers to card guides.
//
// Updated: 10/5/2017
// Rev.: 0.05
// By: Robert S. Rau
// Changes: Added extra width to camera flex so it doesn't snag. Fixed Pi Zero LED cone allignment. Added Battery well for Panasonic BR-435 fishing lure battery, see Digi-Key. More room for Deans connector.
//
// Updated: 10/7/2017
// Rev.: 0.06
// By: Robert S. Rau
// Changes: PyFly USB connector size increased in Z, USB connector pins added on bottom of board.
// Thinned and lengthend Deans power connector, narrowed LED cones by 2mm.
// Added super cap. Added serial connector space so right side can slide in.
// Lengthened servo connector to remove sliver caused by serial connector change.
// Added space for Tach connector and room on right side to slide in.
//
// Updated: 10/8/2017
// Rev.: 0.07
// By: Robert S. Rau
// Changes: ToDo list updated. Added CameraFeatures option.
//
// Updated: 11/18/2017
// Rev.: 0.08
// By: Robert S. Rau
// Changes: ToDo list updated. Battery well no longer intersects screw cylinder. Clearance for remaining parts, option for old PyFly (1.0)
//
// Updated: 11/18/2017
// Rev.: 0.08
// By: Robert S. Rau
// Changes: Camera's camera connector depth changed from 3mm to 2.6. Main wiring channel divided into two parts, USB end made smaller to allow for a step for the two haves to mate against.
//
// Updated: 1/1/2023
// Rev.: 0.09
// By: Robert S. Rau
// Changes: Started mods for ArduCam 16MP
//
// Updated: 1/4/2023
// Rev.: 0.10
// By: Robert S. Rau
// Changes: Made more room for ArduCam 16MP camera
//
// Updated: 8/22/2023
// Rev.: 0.11
// By: Robert S. Rau
// Changes: Opened up Deans power connector area so PiFly would slide in eaiser. Expanded PCB thickness, 1.65->1.72
//
// Updated: 8/23/2023
// Rev.: 0.12
// By: Robert S. Rau
// Changes: Added opening for Pi Zero USB connectors. Increased HDMI connector opening and connector access. Increased PiFly board thickness.
//
// ToDo list
// Add channel for tie-wrap to hold the thing together
// Add board supports (slots) and space for analog adapter board
// more height to W1 & W2
// Cutout for Pi connectors leaves filiment strands
// Quad copter version should allow for non omni antenna
// Room for right side to slide over differential pressure sensor.
// High current drive needs to be taller and wider
// No room for SMT parts on right side cage
// Should fork and do a old PyFly version cage
// clearance for Q4, R17, C43
//
//
//
//
//
// IMPORTANT NOTES
//
// For rocket applications:
// 1) Any openings on your body tube for camera. LEDs, or button will affect the air pressure in the payload cavaity.
// This will affect the barametric altimeter's reading. Make sure the body tube openings are at a neutral pressure
// point down the side of your rocket.
//
//
//
//
//Printing
// Cura settings
// Layer Height 0.2mm
// Wall thickness 1mm
// Infill 15%
// Generate Support Yes
// Support structure Tree
// Support Branch angle 40°
// Support Overhang Angle 50°
// Support Placement Touching Buildplate
// Support pattern Lines
// Support Interface Pattern Zig Zag
// Buildplate Adhesion Type None
// Print left side with camera pointing to side.
//
//
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// USER PARAMETERS
// Here you set up which side of the clam shell you want to render/print, size of your body tube, and such
// for the left side, set CageLeftSide to true, for the right side, set CageLeftSide to false.
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
CageLeftSide = true; // Set this true for one half, false for the other half. Left side has HDMI connector, Right side has backup battery.
GPSAntennaSupport = false; // set to true to surround the GPS antenna with plastic. NOTE: This will change the dielectric constant around the antenna, use thin walls and low fill if set to true.
HDMIUsed = true; // make opening for mating HDMI connector to the Raspberry Pi Zero
U8LargeAccess = false; // true to carve out more area around differential pressure sensor, U8
//MntCylinderDia = 38.1; // 38mm rocket motor tube
//MntCylinderDia = 52.65; // Wildman coupler tube
//MntCylinderDia = 54.6; // Wildman body tube
MntCylinderDia = 39.1; // Estes BT-
//MntCylinderDia = 75.78; // 2.6in rocket body tube
//MntCylinderDia = 102; // 4in rocket body tube
//MntCylinderDia = 29.5; // use for minimum rectangle
//
//
// Do you want to mount the camera on the left side (the right side has wire channel)?
CameraFeatures = true;
//
// This give you two options for camera mounting and video/still requirements. By default, CamFlip=false, the Pi camera produces images with the
// correct orientation with the flex cable comming out the bottom. For the camera to be in this orientation the flex cable must
// get a twist, which uses a bit of cable routing volume. You can set CamFlip to true and have nice flex cable routing but you
// need to flip the image in software. raspivid must use the -ro 180 option, and raspistill must use -vf -hf options.
CamFlip = true;
ExtraDepthForLongerLenses = 2.7; // for Arducam 16MP with imx519 autofocus sensor
//ExtraDepthForLongerLenses = 0; // for Raspberry Pi camera 2
//
OldPyFly = true; // This removes plastic around the new mounting holes and the old PyFly reset switch. Removes plastic for power supply mod.
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//
// Overall circle/sphere definition
$fn=90;
module externalCylinder( diameter, length) {
rotate( a=90, v=[0,1,0]) {cylinder(h=length, d=diameter, center=true );}
}
// Model of space required for PyFly HAT board
//
// Written: 9/10/2017
// Rev.: 0.01
// By: Robert S. Rau
//
//
// Coordinate system referenced to Osmand PCB layout coordinates. The Z zero is the board top, layer 1, for module PyFlyBoardNoHoles.
// There is a Z coordinate shift in module PyFlyBoard.
//
//
// PCB
PCBThickness = 2.0; // PiFly nominal PCB thickness is 1.6mm. Increased. & again on 8/26/2023 (3D print doesn't have a consistent width from end to end.
PyFlyZoffset = 0.5;
module PyFlyLEDCone(Xpos,Ypos,Col) // Places a spot at test pad point, coloured to show pad function
{
translate([Xpos,Ypos,PCBThickness/4]) {
color(Col);
rotate( a=180, v=[1,0,0]) cylinder(h=100,r1=1.2,r2=8,center=false);
}
}
module PyFlyButtonCone(Xpos,Ypos,Col) // Places a spot at test pad point, colored to show pad function
{
translate([Xpos,Ypos,PCBThickness/4]) {
color(Col);
rotate( a=180, v=[1,0,0]) cylinder(h=100,r1=.7,r2=10,center=false);
}
}
module PyFlyBoardNoHoles() {
translate([-0.25,-0.25,0]) cube([151.1,29.75,PCBThickness]); //PCB 0.5mm oversize slot
// new PyFly 2.00 features
if (OldPyFly == false){
translate([-4.24,-0.25,0]) cube([4.01,29.75,PCBThickness]); //Extra length of version 2.00
}
// shape to make card guide champhers
hull()
{
translate([-0.25,-0.25+5,0]) cube([150.5, 29.75-10, PCBThickness]);
translate([-0.25,-0.25+6,-1]) cube([150.5, 29.75-12, PCBThickness+2]);
translate([-0.25,-0.25+6,-1]) cube([150.5, 29.75-12, PCBThickness+2]);
}
// First wiring channel covers from the GPS end of the board to just pass the Pi Zero, this channel is a little bigger than the next.
hull() {
translate([-1,15,(PCBThickness-2.6 )]) rotate(a=90, v=[0,1,0]) cylinder(d=17.5,h=(100), center=false); //wiring channel (opening down the center, above and below the boards)
translate([-1,15,(PCBThickness + 2.39)]) rotate(a=90, v=[0,1,0]) cylinder(d=17.5,h=(100), center=false); //wiring channel 2
}
// Second wiring channel picks up where the first left off, from just beyond the Pi Zero past the USB connector. It doesn't go as deep to allow a step for the two haves to mate against each other
hull() {
translate([98,15,(PCBThickness-1.3 )]) rotate(a=90, v=[0,1,0]) cylinder(d=17.5,h=(100), center=false); //wiring channel (opening down the center, above and below the boards)
translate([98,15,(PCBThickness + 2.39)]) rotate(a=90, v=[0,1,0]) cylinder(d=17.5,h=(100), center=false); //wiring channel 2
}
translate([62.5,15,(PCBThickness - 0.1)-3.2]) cube([53,30,4], center=true); // Space between Zero and PyFly
translate([0,-3.1,(PCBThickness - 0.1)-4.4]) cube([24,14.7,96]); // Servo connectors
translate([-2.54,-4,(PCBThickness - 0.1)-3.2]) cube([2.7,16,96]); // Dual Servo connector
if (CageLeftSide)
{
translate([0,16.18,(PCBThickness + 0.39)]) rotate(a=270, v=[0,1,0]) cylinder(d=20,h=(39.0),center=false); //GPS antenna
}
else
{
hull() {
translate([0,16.18,(PCBThickness + 0.39)]) rotate(a=270, v=[0,1,0]) cylinder(d=20,h=(39.0),center=false); //GPS antenna
translate([0,-28,(PCBThickness + 0.39)]) rotate(a=270, v=[0,1,0]) cylinder(d=20,h=(39.0),center=false); //GPS antenna
}
}
translate([62.23, 26.4,(PCBThickness - 0.1)-2.5]) cube([52,5.2,8.5], center=true); // Pi connector
translate([152, 8.57,PCBThickness-4.5]) cube([15.5,13.5,9], center=true); //USB connector
translate([147.77, 8.57,PCBThickness+1.0]) cube([4,14.7,1.9], center=true); //USB connector pins
translate([152+7.75+20, 8.57,PCBThickness-3.75]) cube([44,20,15], center=true); //USB Device
translate([3.81, 24,(PCBThickness - 0.1)+5.5+50]) cube([5.2,2.8,17+100], center=true); // Battery connector
hull()
{
translate([24.848, 17.58,(PCBThickness - 0.1)+5.5+50]) cube([2.2,8.4,17+100], center=true); // Serial connector
translate([24.848, -17.58,(PCBThickness - 0.1)+5.5+50]) cube([2.2,8.4,17+100], center=true); // Serial connector
}
hull()
{
translate([82.73415, 12.37,(PCBThickness - 0.1)+5.5+50]) cube([6.6,10.7,17+100], center=true); // Tach connector
translate([82.73415, -10,(PCBThickness - 0.1)+5.5+50]) cube([6.6,10.7,17+100], center=true); // Tach connector
}
translate([139.25, 40,PCBThickness-7.25]) cube([23.5,57.5,21], center=true); // High current connector J6 left & right side
translate([133.1, 2.85-1,PCBThickness+5.5]) cube([19,20,17], center=true); // Keypad connector
translate([138.35, 9.3218,PCBThickness+5.5+20]) cube([5,13,57], center=true); // analog connector J7
translate([55.734, 11.94,PCBThickness+5.5]) cube([12,14,11], center=true); // Differential pressure sensor, U8, right side
translate([99.61, 5.73,PCBThickness+2.3]) cube([5.1,8,7], center=true); // Interrupt jumpers
translate([41.4, 5,PCBThickness+12.5+50]) cube([5.4,16,115], center=true); // Audio connector, P4
translate([115, 12.7,PCBThickness+2.5]) cube([17,10,200], center=true); // Deans Power connector P1
translate([113, 18.5,PCBThickness-13.5]) cube([21,9.5,11], center=true); // Deans Power connector P1, insertion well, long enough to take out a little foot on the end.
if (OldPyFly == true) {
translate([115, 03,PCBThickness-6]) cube([15,9.5,9], center=true); // Power supply modification clearance-----remove with new board.
}
translate([72.5, 5.3,PCBThickness+0.5]) cube([32,10,4], center=true); // parts - left side
hull()
{
translate([11.8872, 20.3484,PCBThickness-7.2]) cylinder(d=13,h=9, center=true); // GPS Super capacitor C2
translate([11.8872, 14.3484,PCBThickness-7.2]) cylinder(d=13,h=9, center=true); // GPS Super capacitor C2
}
if (OldPyFly)
{
translate([18.5,22,PCBThickness/2-5.5]) cube([7.75,7,5.5], center=false); // parts: Old PyFly reset button, SW1
translate([25.5,26,PCBThickness/2])cube([6.5,6.5,6],center=true); // Microphone U22
translate([111,26,PCBThickness/2])cube([6.5,6.5,6],center=true); // Clearance for R52, R30 et. all (PiFly doesn't support this hole)
}
translate([1.5,17,PCBThickness/2-3]) cube([20.75,29.25-17,6], center=false); // parts: R40 right side
translate([28.75,17,PCBThickness/2-3]) cube([8.25,29.25-17,6], center=false); // parts: Q3, R56 (PiFly doesn't support this hole) right side
translate([55, 6.5,PCBThickness/2]) cube([21,10,5], center=true); // parts: PP35, PP23, R6 Left side
translate([40.5, 5.3,PCBThickness/2]) cube([8,10,5], center=true); // parts: D2 left side
translate([15.4, 5,PCBThickness/2]) cube([30.6,10,5.5], center=true); // parts: U15, U10 left side
translate([122.25, 6.25,PCBThickness/2]) cube([55.5,10,5], center=true); // parts: C27, C28, R67 left side
translate([1.5,3,PyFlyZoffset-3]) cube([17.5,23,3], center=false); // parts GPS LEDs resistors left & right side
translate([1,3,PyFlyZoffset-3]) cube([18,8,3], center=false); // parts bottom of servo connectors P2, P3, P10 left side
translate([114,17,PCBThickness/2-3]) cube([14,29.25-17,6], center=false); // parts High side driver
translate([90.5,17,PCBThickness/2]) cube([17.5,29.25-17,3], center=false); // parts RF amplifier right side
translate([94.5,17,PCBThickness/2-3]) cube([13.5,29.25-17,3], center=false); // parts High side driver control & A/D stuff right side
PyFlyLEDCone(4.7,27.686,"Yellow"); // LED
PyFlyLEDCone(4.7,26.543,"Yellow"); // LED
PyFlyLEDCone(105.12,2.51,"Yellow"); // LED
PyFlyLEDCone(107.98,21.107,"Yellow"); // LED
translate([18.75,27.15,PCBThickness-2.0]) cube([5,3,3], center=true); // button block
translate([18.75,27.15,PCBThickness-3.7]) PyFlyButtonCone(0,0,"Blue"); // button cone
MountingHoles();
}
// Cutout for USB test point wires
module USBWireCutout() {
hull() {
translate([44.57,0,0]) cylinder(r=0.01,h=PCBThickness * 2.1,center=true);
translate([46.8,1.5,0]) cylinder(r=0.01,h=PCBThickness * 2.1,center=true);
translate([54.2,1.5,0]) cylinder(r=0.01,h=PCBThickness * 2.1,center=true);
translate([56.43,0,0]) cylinder(r=0.01,h=PCBThickness * 2.1,center=true);
}
}
module MountingHoles() {
translate([33.5,3.5,0])cylinder(d=2.743,h=PCBThickness*20.1,center=true);
translate([91.5,3.5,0])cylinder(d=2.743,h=PCBThickness*20.1,center=true);
translate([25.5,26,0])cylinder(d=2.743,h=PCBThickness*20.1,center=true);
translate([111,26,0])cylinder(d=2.743,h=PCBThickness*20.1,center=true);
translate([158,26,0])cylinder(d=2.743,h=PCBThickness*20.1,center=true); // mostly for old PiFly since it has no screw holes on this side
}
module PyFlyBoard() {
// translate([-62.5,-15,PyFlyZoffset]) difference () {
translate([-62.5,-15,PyFlyZoffset]) {
PyFlyBoardNoHoles();
//USBWireCutout();
//MountingHoles();
}
}
module ScrewFlats() {
translate([-62.5,-15,0.5]) translate([33.5,3.5,0])cylinder(d=7,h=50,center=true);
translate([-62.5,-15,0.5]) translate([91.5,3.5,0])cylinder(d=7,h=50,center=true);
translate([-62.5,-15,-0.5]) translate([25.5,26,0])cylinder(d=7,h=50,center=true);
translate([-62.5,-15,-0.5]) translate([111,26,0])cylinder(d=7,h=50,center=true);
translate([-62.5,-15,-0.5]) translate([158,26,0])cylinder(d=7,h=50,center=true); // mostly for old PiFly since it has no screq holes on this side
}
// Pi Zero model for checking other models
// 0,0,0 is centre of PCB, bottom face
// This model is for V1.2
// PCB size variables
PiSizeX = 65.4;
PiSizeY = 30.4;
PiSizeZ = 1.8; // new zeros are thicker 8/22/2023 & again on 8/26/2023
PiCornerRad = 3.52;
PiHoleEdge = 3.5; // Mount holes are 3.5mm from each edge
PiHoleDia = 2.75;
PiHoleRad = PiHoleDia / 2;
PiHoleClearRad = 3.0; // Mount holes have 6 Dia clear on PCB
// Component connector centrelines from Pi centreline
PiSDX = -24.5; // SD holder
PiSDY = 1.9;
PiUSBX = 8.9; // Data (USB)
PiUSBY = -11;
PiOTGX = 21.5; // Power (OTG)
PiOTGY = -11;
PiHDMIX = -20.1; // HDMI
PiHDMIY = -6.4;
PiHDMImcX = -20.1; // HDMI mating connector
PiHDMImcY = -7;
PiHDMImcZ = -10;
PiLEDX = 27.38; // LED
PiLEDY = -7.87;
PiCAMX = 32.5; //Camera connector
PiCAMY = 0;
// Component connector sizes
PiSDsizeX = 11.5;
PiSDsizeY = 12.0;
PiSDsizeZ = 1.3; // Connector height (may be from point below surface of board (center = Zsize/2.3 )
PiUSBsizeX = 10; // extra mm needed for little tabs on end of USB connectors
PiUSBsizeY = 18.0;
PiUSBsizeZ = 4; // USB connectors have lips that extend higer and lower that the main (center = Zsize/2.3 )
PiHDMIsizeX = 13;
PiHDMIsizeY = 26;
PiHDMIsizeZ = 4.3;
PiHDMImcsizeX = 20;
PiHDMImcsizeY = 100;
PiHDMImcsizeZ = 100;
PiCAMsizeX = 8;
PiCAMsizeY = 17;
PiCAMsizeZ = 1.8;
// Keepout sizes
PiKOLengthX = PiSizeX;
PiKOLengthY = 17;
PiKOLengthZ = 1.9;
PiKOWidthX = 52.5;
PiKOWidthY = PiSizeY;
PiKOWidthZ = 1.6;
// SOC centrelines and sizes
PiSOCX = -2.5;
PiSOCY = -2;
PiSOCsizeX = 12;
PiSOCsizeY = 12;
PiSOCsizeZ = 1.2;
// Mount hole dims from centre lines
PiHoleX = PiSizeX/2 - PiHoleEdge;
PiHoleY = PiSizeY/2 - PiHoleEdge;
//
// Modules used for Pi model
//
module PiDrawPad(Xpos,Ypos,Di,Col) // Places a spot at test pad point, coloured to show pad function
{
translate([Xpos,Ypos,PiSizeZ/4])
color(Col)
cylinder(h=PiSizeZ*2/3,d=Di,center=true);
}
module PiPCBhole(Xpos,Ypos) // Cuts a hole through PCB
{
translate([Xpos,Ypos,PiSizeZ/2])
cylinder(h=2*PiSizeZ,d=PiHoleDia,center=true);
}
module PiComponent(Xpos,Ypos,Xsize,Ysize,Zsize,Col) // Makes a block to represent a component on the upper face
{
translate([Xpos,Ypos,PiSizeZ + Zsize/2.55]) color(Col) // USB connectors have lips that extend higer and lower that the main connector height
cube([Xsize,Ysize,Zsize+0.5], center=true);
}
module PiLEDCone(Xpos,Ypos,Col) // Places a spot at test pad point, coloured to show pad function
{
translate([Xpos,Ypos,PiSizeZ/4]) {
color(Col);
cylinder(h=60,r1=1.2,r2=10,center=false);
}
}
//
// This is the main routine and can be called from outside
//
module PiZeroBody() // Models the Pi.
{
color("Green")
//difference()
// {
hull() // PCB shape
{
translate([-PiHoleX,-PiHoleY,PiSizeZ/2])
cylinder(r=PiCornerRad,h=PiSizeZ,center=true);
translate([PiHoleX,-PiHoleY,PiSizeZ/2])
cylinder(r=PiCornerRad,h=PiSizeZ,center=true);
translate([PiHoleX,PiHoleY,PiSizeZ/2])
cylinder(r=PiCornerRad,h=PiSizeZ,center=true);
translate([-PiHoleX,PiHoleY,PiSizeZ/2])
cylinder(r=PiCornerRad,h=PiSizeZ,center=true);
}
// shape to make card guide champhers
hull()
{
translate([0,0,PiSizeZ/2]) cube([PiSizeX, PiSizeY-12, PiSizeZ],center=true);
translate([0,0,PiSizeZ/2]) cube([PiSizeX, PiSizeY-14, PiSizeZ+2],center=true);
}
// Corner screw holes
PiPCBhole(-PiHoleX,-PiHoleY);
PiPCBhole(PiHoleX,-PiHoleY);
PiPCBhole(PiHoleX,PiHoleY);
PiPCBhole(-PiHoleX,PiHoleY);
// }
PiComponent(PiSOCX,PiSOCY,PiSOCsizeX,PiSOCsizeY,PiSOCsizeZ,"Black"); // Processor
PiComponent(PiSDX,PiSDY,PiSDsizeX,PiSOCsizeY,PiSOCsizeZ,"Silver"); // SD card
PiComponent(PiHDMIX,PiHDMIY,PiHDMIsizeX,PiHDMIsizeY,PiHDMIsizeZ,"Silver"); // HDMI
if (HDMIUsed) {
//PiComponent(PiHDMImcX,PiHDMImcY,PiHDMImcsizeX,PiHDMImcsizeY,PiHDMImcsizeZ,"Blue"); // HDMI mating connector
translate([PiHDMImcX,-PiHDMImcsizeY/2-16,-PiHDMImcsizeZ/2+18]) //
// translate([PiHDMImcX,PiHDMImcY-PiHDMImcsizeY/2,PiHDMImcsizeZ + PiHDMImcsizeZ/2.3]) // USB connectors have lips that extend higer and lower that the main connector height
cube([PiHDMImcsizeX+2,PiHDMImcsizeY,PiHDMImcsizeZ], center=true);
}
PiComponent(PiUSBX,PiUSBY,PiUSBsizeX,PiUSBsizeY,PiUSBsizeZ,"Silver"); // USB
PiComponent(PiOTGX,PiOTGY,PiUSBsizeX,PiUSBsizeY,PiUSBsizeZ,"Silver"); // Power
PiComponent(PiCAMX,PiCAMY,PiCAMsizeX,PiCAMsizeY,PiCAMsizeZ,"Silver"); // Camera
PiComponent(0,0,PiKOLengthX,PiKOLengthY,PiKOLengthZ,"Yellow"); // Keep Out
PiComponent(0,0,PiKOWidthX,PiKOWidthY,PiKOWidthZ,"Yellow"); // Keep Out
PiLEDCone(PiLEDX,PiLEDY,"Green");
}
// Pi Zero in position
module PiZeroInPosition() {
rotate(a=180, v=[0,0,1]) {
translate ([0, 0, -2]) {
rotate(a=180, v=[1,0,0]) {
PiZeroBody();
}
}
}
}
// These two cubes are used to cut the model in two parts
module CutCubes() {
translate([0,250,-7]) cube([500,500,500], center=true);
translate([0,-250,10]) cube([500,500,500], center=true);
}
// Camera stuff
CamPCBThickness = 1.1;
CamSizeY = 27; //extra width so the camera can be removed (camera width is 25mm)
CamSizeZ = 24.9;
CamSensorHeight = 5.1; // This matches the Pi Camera V2
CamLensOffsetZ = 2.5;
CamLensHeight = 4.86;
CamBotEleHeight=2.6-CamPCBThickness; // expressed this way since it is the easiest way to measure
CamMountingHoleCCZ = 12.5;
CamMountingHoleCCY = 21;
CamConnectorZ = 7.6; // connector depth from board edge into board
CamFlexWidth = 18;
// mounting holes
module CamHoles() {
translate([0,CamMountingHoleCCY/2.0,CamMountingHoleCCZ]) {
rotate( a=90, v=[0,1,0]) { cylinder(d=1.7,h=100,center=true); }
}
translate([0,-CamMountingHoleCCY/2.0,CamMountingHoleCCZ]) {
rotate( a=90, v=[0,1,0]) { cylinder(d=1.7,h=100,center=true); }
}
translate([0,CamMountingHoleCCY/2.0,0]) {
rotate( a=90, v=[0,1,0]) { cylinder(d=1.7,h=100,center=true); }
}
translate([0,-CamMountingHoleCCY/2.0,0]) {
rotate( a=90, v=[0,1,0]) { cylinder(d=1.7,h=100,center=true); }
}
}
module CamPCB() {
difference() {
translate([CamPCBThickness/2.0+50,0,CamLensOffsetZ+5]) {
cube([CamPCBThickness+100,CamSizeY,CamSizeZ], center=true);
}
CamHoles();
}
}
// bottom side electronics
module CamBotEle() {
translate([-CamBotEleHeight/2.0+0.01,0,CamMountingHoleCCZ/2.0]) {
cube([CamBotEleHeight,CamSizeY-8,9], center=true); // camera component clearance side to side
}
translate([-CamBotEleHeight/2.0+0.01,0,CamLensOffsetZ]) {
cube([CamBotEleHeight,CamMountingHoleCCY-3,CamSizeZ], center=true);
}
translate([-CamBotEleHeight/2.0+0.01,0,CamLensOffsetZ+4]) rotate([0,90,0]) {
cylinder(h=CamBotEleHeight,r=11, center=true); // used to nick away plastic for components close to mounting holes (on the diagonal)
}
// connector
translate([-1.4,0,-CamSizeZ/2.0+CamLensOffsetZ+CamConnectorZ/2.0]) {
cube([2.9,23.8,CamConnectorZ], center=true); // connector width changed from 22 to 23.4 for ArduCam 16MP camera
}
// Flex
translate([-1.57+50,0,-CamSizeZ/2.0+CamLensOffsetZ-0.9]) {
cube([0.4+100,CamFlexWidth+.5,12], center=true);
}
// Room for Flex fold inside left side
translate([-5,0,-32]) {
cube([10,15,25], center=true); // only as wide as narrower part of flex
}
}
module CamPocket() {
CamPCB();
CamBotEle();
}
// !CamPocket();
//!translate([0,0,0]) rotate(a=90,[0,1,0]) CamPocket();
module FullCage() {
difference() {
externalCylinder(MntCylinderDia,200);
// translate([0,0,3]) cube([200,36,25], center=true); // minimum rectangle for airplanes and quadcopters
PyFlyBoard();
PiZeroInPosition();
// select only one for the CutCubes, this makes the left or right side of the cage,comment whole if clause to see whole cage.
if (CageLeftSide)
{
translate([0,0,247.99]) CutCubes(); // Left side
}
else
{
translate([0,0,247.99-500]) CutCubes(); // Right side
}
translate([0,0,-37])ScrewFlats();
translate([0,0,35.5])ScrewFlats();
hull() {
translate([48,-8,116]) cube([220,7,200],center=true); // wire channel
translate([48,-10.5,114]) cube([220,7,200],center=true); // wire channel
translate([48,-11.5,113]) cube([220,3,200],center=true); // wire channel
translate([48,-100,113]) cube([220,7,200],center=true); // wire channel
}
hull() {
translate([80,-1,-116]) cube([60,4,200],center=true); // wire channel
translate([80,-2.5,-113]) cube([60,4,200],center=true); // wire channel
translate([80,-5,-116]) cube([60,4,200],center=true); // wire channel
}
if (CameraFeatures)
{
// camera pocket
if (CamFlip) {
translate([0,0,-(sqrt(((MntCylinderDia/2)*(MntCylinderDia/2))-16)-CamPCBThickness-CamLensHeight)+ExtraDepthForLongerLenses]) rotate(a=90,v=[0,1,0]) CamPocket();
// camera flex cable entry to inside from camera
translate([-18,0,-50]) cube([4,CamFlexWidth+0.5,100], center=true);
}
else
{
translate([0,0,-(sqrt(((MntCylinderDia/2)*(MntCylinderDia/2))-16)-CamPCBThickness-CamLensHeight)]) rotate(a=180,v=[0,0,1]) rotate(a=90,v=[0,1,0]) CamPocket();
// camera flex cable entry
translate([18,0,-50]) cube([4,CamFlexWidth+0.5,100], center=true);
}
// Camera lens allignment notch
translate([0,0,-(sqrt(((MntCylinderDia/2)*(MntCylinderDia/2))-16))-1.5]) cube([200,1,3],center=true);
}
// battery cable channel
translate([-59,0,MntCylinderDia/2+5.5]) cube([5,100,20], center=true);
// serial connector wire channel
translate([24.848-62.5, -5,MntCylinderDia/2+4+50]) cube([2.2,8.4,17+100], center=true); // Serial connector
translate([0,3.5,-5.6]) cube([80,7,7],center=true); // cutaway so sliding cage together doesn't crush camera flat cable
// battery well
hull() // battery body
{
translate([-59,0.866*(MntCylinderDia-4.3)/2, 0.5*(MntCylinderDia-4.3)/2-1]) rotate( a=90, v=[0,1,0]) cylinder(d=4.2, h=31);
translate([-59,0.866*(MntCylinderDia+1)/2, 0.5*(MntCylinderDia+1)/2-1]) rotate( a=90, v=[0,1,0]) cylinder(d=4.2, h=31);
}
hull() // battery pin
{
translate([-65,0.866*(MntCylinderDia-4.3)/2, 0.5*(MntCylinderDia-4.3)/2-1]) rotate( a=90, v=[0,1,0]) cylinder(d=1.2, h=31);
translate([-65,0.866*(MntCylinderDia+1)/2, 0.5*(MntCylinderDia+1)/2-1]) rotate( a=90, v=[0,1,0]) cylinder(d=1.2, h=31);
}
hull() // battery wire path
{
translate([-61.5,0.866*(MntCylinderDia-4.3)/2, 0.5*(MntCylinderDia-4.3)/2]) rotate( a=90, v=[0,1,0]) cylinder(d=2.4, h=5.0);
translate([-61.5,0,(MntCylinderDia+1)/2]) rotate( a=90, v=[0,1,0]) cylinder(d=2.4, h=5.0);
}
translate([49,-15,40]) cube([25,20,64.1], center=true); // remove "hook" around power connector and room for W1 W2
if (CageLeftSide == false) {
translate([30,-9,4.6]) rotate([24,0,0]) cube([170,20,10], center=true); // to make more printable without support (interferes with left side
}
if (CameraFeatures)
{
// opening for camera flex cable to wrap around end of Zero, this way the flex won't catch on the ledge.
translate([26,-3,-9]) cube([23,6,5], center=true);
}
if (GPSAntennaSupport == false) {
translate([-90,-9,4.6]) cube([40,500,500], center=true); //
}
if (U8LargeAccess == true) {
translate([-62.5,-15,PyFlyZoffset]) translate([62, 10,PCBThickness+7]) cube([37,26,14], center=true); // Differential pressure sensor, U8, Large access, right side
}
}
}
FullCage();