As far as I can tell, Raspberry Pi cases are a solved problem, so 3D printing an intricate widget to stick a Pi on the back of an HQ camera seems unnecessary unless you really, really like solid modeling, which, admittedly, can be a thing. All you really need is a simple adapter between the camera PCB and the case of your choice:

A quartet of 6 mm M2.5 nylon spacers mount the adapter to the camera PCB:

The plate has recesses to put the screw heads below the surface. I used nylon screws, but it doesn’t really matter.
The case has all the right openings, slots in the bottom for a pair of screws, and costs six bucks. A pair of M3 brass inserts epoxied into the plate capture the screws:

Thick washers punched from an old credit card go under the screws to compensate for the case’s silicone bump feet. I suppose Doing the Right Thing would involve 3D printed spacers matching the cross-shaped case cutouts.
Not everyone agrees with my choice of retina-burn orange PETG:

Yes, that’s a C-mount TV lens lurking in the background, about which more later.
The OpenSCAD source code as a GitHub Gist:
| // Raspberry Pi HQ Camera Backplate | |
| // Ed Nisley KE4ZNU 2020-09 | |
| //– Extrusion parameters | |
| /* [Hidden] */ | |
| ThreadThick = 0.25; | |
| ThreadWidth = 0.40; | |
| HoleWindage = 0.2; | |
| function IntegerMultiple(Size,Unit) = Unit * ceil(Size / Unit); | |
| function IntegerLessMultiple(Size,Unit) = Unit * floor(Size / Unit); | |
| Protrusion = 0.1; // make holes end cleanly | |
| inch = 25.4; | |
| ID = 0; | |
| OD = 1; | |
| LENGTH = 2; | |
| //- Basic dimensions | |
| CamPCB = [39.0,39.0,1.5]; // Overall PCB size, plus a bit | |
| CornerRound = 3.0; // … has rounded corners | |
| CamScrewOC = [30.0,30.0,0]; // … mounting screw layout | |
| CamScrew = [2.5,5.0,2.2]; // … LENGTH = head thickness | |
| Standoff = [2.5,5.5,6.0]; // nylon standoffs | |
| Insert = [3.0,4.0,4.0]; | |
| WallThick = IntegerMultiple(2.0,ThreadWidth); | |
| PlateThick = Insert[LENGTH]; | |
| CamBox = [CamPCB.x + 2*WallThick, | |
| CamPCB.y + 2*WallThick, | |
| Standoff.z + PlateThick + CamPCB.z + 1.0]; | |
| PiPlate = [90.0,60.0,PlateThick]; | |
| PiPlateOffset = [0.0,(PiPlate.y – CamBox.y)/2,0]; | |
| PiSlotOC = [0.0,40.0]; | |
| PiSlotOffset = [3.5,3.5]; | |
| NumSides = 2*3*4; | |
| TextDepth = 2*ThreadThick; | |
| //———————- | |
| // Useful routines | |
| module PolyCyl(Dia,Height,ForceSides=0) { // based on nophead's polyholes | |
| Sides = (ForceSides != 0) ? ForceSides : (ceil(Dia) + 2); | |
| FixDia = Dia / cos(180/Sides); | |
| cylinder(r=(FixDia + HoleWindage)/2,h=Height,$fn=Sides); | |
| } | |
| //———————- | |
| // Build it | |
| difference() { | |
| union() { | |
| hull() // camera enclosure | |
| for (i=[-1,1], j=[-1,1]) | |
| translate([i*(CamBox.x/2 – CornerRound),j*(CamBox.y/2 – CornerRound),0]) | |
| cylinder(r=CornerRound,h=CamBox.z,$fn=NumSides); | |
| translate(PiPlateOffset) | |
| hull() | |
| for (i=[-1,1], j=[-1,1]) // Pi case plate | |
| translate([i*(PiPlate.x/2 – CornerRound),j*(PiPlate.y/2 – CornerRound),0]) | |
| cylinder(r=CornerRound,h=PiPlate.z,$fn=NumSides); | |
| } | |
| hull() // camera PCB space | |
| for (i=[-1,1], j=[-1,1]) | |
| translate([i*(CamPCB.x/2 – CornerRound),j*(CamPCB.y/2 – CornerRound),PlateThick]) | |
| cylinder(r=CornerRound,h=CamBox.z,$fn=NumSides); | |
| translate([0,-CamBox.y/2,PlateThick + CamBox.z/2]) | |
| cube([CamScrewOC.x – Standoff[OD],CamBox.y,CamBox.z],center=true); | |
| for (i=[-1,1], j=[-1,1]) // camera screws with head recesses | |
| translate([i*CamScrewOC.x/2,j*CamScrewOC.y/2,-Protrusion]) { | |
| PolyCyl(CamScrew[ID],2*CamBox.z,6); | |
| PolyCyl(CamScrew[OD],CamScrew[LENGTH] + Protrusion,6); | |
| } | |
| for (j=[-1,1]) // Pi case screw inserts | |
| translate([0,j*PiSlotOC.y/2 + PiSlotOffset.y,-Protrusion] + PiPlateOffset) | |
| PolyCyl(Insert[OD],2*PiPlate.z,6); | |
| translate([-PiPlate.x/2 + (PiPlate.x – CamBox.x)/4,0,PlateThick – TextDepth/2] + PiPlateOffset) | |
| cube([15.0,30.0,TextDepth + Protrusion],center=true); | |
| } | |
| translate([-PiPlate.x/2 + (PiPlate.x – CamBox.x)/4 + 3,0,PlateThick – TextDepth – Protrusion] + PiPlateOffset) | |
| linear_extrude(height=TextDepth + Protrusion,convexity=2) | |
| rotate(-90) | |
| text("Ed Nisley",font="Arial:style=Bold",halign="center",valign="center",size=4,spacing=1.05); | |
| translate([-PiPlate.x/2 + (PiPlate.x – CamBox.x)/4 – 3,0,PlateThick – TextDepth – Protrusion] + PiPlateOffset) | |
| linear_extrude(height=TextDepth + Protrusion,convexity=2) | |
| rotate(-90) | |
| text("KE4ZNU",font="Arial:style=Bold",halign="center",valign="center",size=4,spacing=1.05); |













