COTS-LoRa 3D-printed TOH shell

As mentioned in another comment, I’m interested in this as well and I think it might be a good option to put COTS-LoRa-components in a 3D-printed TOH shell instead of designing all the hardware.

Today, I was curious about co-designing stuff with AI and decided to mess around with the LoRa TOH as an example.

If you start with nothing and use declarative languages like OpenSCAD or build123d, generating even complex geometries with a few prompts can be surprisingly effective. In this case, however, I needed to combine the design by @thejiral from this thread with modifications to accomodate the LoRa-Boards (the Seeed XIAO I have), cables and antenna.

That’s a whole other can of worms because depending on the source format (in this case, .STEP) you feed your LLM with a whole confusing mess of data. It needed more prompts that I’m happy with and the result is not great but I learned something. ^^ I’ll print and test it, but for future iterations, I will just do the modifications by hand. @thejiral could you tell me what software you designed your TOH in and if the STEP is not the source format, would you mind sharing the base/source file?

In case anybody wants the messy code (it assumes a vscode instance with the OCP-Viewer Extension buf if you remove the second line (from ocp_…) and the last one (show(…), you can use it in anything that speaks Python an can import the build123d library:

from build123d import *
from ocp_vscode import show

# Geometric constants and parameters
xiao_length, xiao_width = 21.0, 17.5
wio_length, wio_width = 21.0, 17.5
cavity_depth = 4.8         # 4.5mm board thickness + 0.3mm tolerance gap
spool_depth = 1.5          # Depth for the cable spool cavity
sma_dia = 6.1              # Press-fit for 6.35mm SMA thread
base_plate_thickness = 1.2 # Estimated thickness of the original TOH backplate

# 7.0mm total thickness seamlessly encloses the 6.1mm connector in the upper edge
target_thickness = 7.0     
wall_thickness = target_thickness - cavity_depth # Results in 2.2mm outer wall
thickening_delta = target_thickness - base_plate_thickness

with BuildPart() as toh_customized:
    # 1. Import and rotation of the base file
    toh_base = import_step("/home/coder/projects/toh-lora/optional_frame-final1-modified.step")
    toh_base = toh_base.rotate(Axis.X, -90)
    add(toh_base)
    
    # 2. Thickening
    planar_z_faces = toh_base.faces().filter_by(GeomType.PLANE).filter_by(Axis.Z)
    back_face = sorted(planar_z_faces, key=lambda f: f.area)[-1]
    extrude(back_face, amount=thickening_delta)
    
    # Calculate Z and Y planes
    bbox = toh_customized.part.bounding_box()
    z_new_bottom = bbox.min.Z
    board_floor_z = z_new_bottom + wall_thickness
    y_min = bbox.min.Y # Case top edge (near camera)
    y_max = bbox.max.Y # Case bottom edge (near pogo pins)
    y_mid = (y_max + y_min) / 2
    
    # 3. Board cavities (compact, shifted 2mm upwards away from pogo pins)
    cavity_plane = Plane(origin=(0, 0, board_floor_z), z_dir=(0, 0, 1))
    with BuildSketch(cavity_plane):
        # XIAO bottom left (-X). Pierces bottom edge for USB-C.
        with Locations((-15, y_max - (xiao_length/2) + 1)):
            Rectangle(xiao_width, xiao_length + 2)
            
        # Wio-SX1262 bottom right (+X), shifted 2mm upwards to clear pogo pins
        with Locations((15, y_max - 27)):
            Rectangle(wio_width, wio_length)
            
        # Routing channel between Wio and XIAO as an isolated slot
        with BuildSketch(mode=Mode.PRIVATE) as route_boards:
            with Locations((-15, y_max - 15), (15, y_max - 17)):
                Circle(4.0)
            make_hull()
        add(route_boards.sketch)
    
    extrude(amount=cavity_depth + 2, mode=Mode.SUBTRACT)
    
    # 4. Spool cavity and coaxial routing
    spool_floor_z = board_floor_z + (cavity_depth - spool_depth)
    spool_plane = Plane(origin=(0, 0, spool_floor_z), z_dir=(0, 0, 1))
    
    with BuildSketch(spool_plane):
        # Spool centered in the MagSafe ring
        with Locations((0, y_mid)):
            SlotOverall(30, 15)
            
        # Cable channel: Wio (+X) to spool (center) via make_hull
        with BuildSketch(mode=Mode.PRIVATE) as route_wio:
            with Locations((15, y_max - 27), (0, y_mid - 6)):
                Circle(1.5)
            make_hull()
        add(route_wio.sketch)
        
        # Cable channel: Spool (center) to antenna (+X) via make_hull
        with BuildSketch(mode=Mode.PRIVATE) as route_sma:
            with Locations((0, y_mid + 6), (20, y_min + 12)):
                Circle(1.5)
            make_hull()
        add(route_sma.sketch)
        
    extrude(amount=spool_depth + 2, mode=Mode.SUBTRACT)
    
    # 5. Press-fit for SMA connector (top right, +X)
    sma_z_center = z_new_bottom + (target_thickness / 2)
    
    sma_plane = Plane(origin=(20, y_min - 1, sma_z_center), z_dir=(0, -1, 0))
    with BuildSketch(sma_plane):
        Circle(radius=sma_dia/2)
        
    extrude(amount=-16, mode=Mode.SUBTRACT)

show(toh_customized)

edit: The components this is designed for:

edit2: Code slightly updated

10 Likes

I designed in Freecad and the std file is extremely messy, not sure it is a great help. I did export those parts from there directly into step.

3 Likes

Well, for better or for worse, here’s the (fugly) prototype for the TOH prepper edition. :smiley: Everything fits more or less well. Some slight adjustments, new print, desolder the pin headers from the Boards, solder in some cable connections and it’s ready. :laughing:

18 Likes

Me too, mee too!
I’d really like to fiddle from an std file and at the end, we’ll perhaps manage to end up with a clean one to share proudly!

3 Likes

This prepper edition looks great. Will there be a stealth version (internal antenna, no hub for external antenna)?

1 Like

I’ve got nothing to hide, just thought the step file looks reasonably clean, unlike the raw file. :wink:

Dig deep at your own risk. The thing with Freecad is that I is still find it a nightmare to change things deeper down with often erratic errors that it is way easier to just keep patching on top of it all. When having to iterate tolerances multiple times that is the result. I do not claim to use Freecad properly but it does the job for me that way.

Here is a link to the file: cTOH-M_raw-files/Backcover14.FCStd at main · thejiral/cTOH-M_raw-files · GitHub

4 Likes

Here’s the second, slightly less fugly prototype. I was still not generous enough with the cavity sizes and I didn’t find any of the nice, thin, flexible multi-core wire that I thought I had so I broke a few of the solder joints when installing the hardware. Worked for a second, though. :smiley:

Ergonomically speaking, I thought this would be ridiculously bad - but actually, compared to foldables or big iPhones in cases or stuff like that, it really isn’t. Apart from the antenna, obviously. Also: I think there’s more than enough space in there to also put in a small battery and a charger board, so the USB-C port of the phone does not have to be in constant use (with the current design, a short USB-C patch cable not show in the pictures goes from the phone into the microcontroller)

11 Likes

How is the grip of the TOH? Strong enough? In the Freecad file there are also the locations of the 4 screw holes (theoretically using two of them should already be sufficient), at least based on the technical drawing from Jolla. I did not test their real world alignment though. In case you want a fail proof connection.

I can’t see place for battery. or do you plan to supply from external one?

Just read the docs: :wink:

@Jolla: How about putting documentation links like the above one into a sticky topic inside the “The Other Half” category, to give future TOH developers a reliable starting point?

3 Likes

These images with large antennas reminds me the 80s or early 90s handheld short wave radios or mobile phones :slight_smile:

3 Likes

Nice.

How about drawing power from the pogo pins?

If you take out the usb connector and the antenna mount, could the hole thing become a few mm less thick?

1 Like

But without using the pogo pins for power and serial connection, how is this solution better than any ready-made client attached to the phone by tape?

I thik snub antenna could work better that is in square notch?

Sorry, couldn’t resist. I :heart: your TOH!

11 Likes

I was hoping for something like this to exist… Now I might have an excuse to make Indra work with meshtasticd.

1 Like

I totally agree but…

It’s the Lilygo TDeck Plus or Pro… :wink:

And it’s Meahcore for sure.

:wink: I absolutely support all things LoRa anyway and I am far from dogmatism. My Pro will go Meshtastic as soon as I find the time and a proper firmware.

1 Like

Nice work, @anon48373651!

I support the idea of including a battery and charging it from the pogo pins. That way, the TOH would stay active even if the phone is switched off. Or enters some power save mode that cuts power to the TOH, if that is a thing - docs seem to indicate that either the TOH has power during identification or always.

Wow, I wish I had the time for projects like these ….. great to see ! :sweat_smile::+1: