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); |