Project and Justifications
GPD Pocket pairs great with the Keyboardio Atreus but it's hard to use them together because . I would like to 3d print some small cantilevers to allow me to place the atreus underneath the GPD and type with the atreus on a flat surface.
It will use my external battery pack as a counter weight, and a place to mount a USB-C hub. I intend to get my Thinkpad out of my Travel inventory with this system. I think even for day trips on My Electric Bike to some parks and coffee shops, having a 7" laptop package is really nice.
I can do most of my development with a more focused and minimal workflow with the smaller screen but with a fairly powerful x86_64 CPU compared to the Android and ARM SBC options. Meanwhile, no one is making a laptop with an ergonomic hardware keyboard, and the GPD is difficult to use as-is[fn:1], and this deployment can still be lighter even if it's more difficult to use.
These should be able to travel with me in the same way as my little Thinkpad Atreus Risers
file:~/org/data/3c/4a9324-28a8-4883-8255-cc39e52a1c4f/atreus-stand.png
It's (designed or computed or programmed) in OpenSCAD.
The code defined below is merged in to a single geometry with union and then exported.
Parameters for the build are provided here; I would like to avoid magic numbers. I know I'm going to spend weeks tweaking these to my printer and the devices themselves.
$atreus_bottom_length = 90;
$stand_width = 4;
$atreus_hook_height = 4;
$atreus_hook_angle = 20;
$riser_height = 50;
$gpd_rotate_down = 10;
$gpd_canti_length = 60;
$gpd_canti_offset = 40;
$gpd_cup_r=5;
$gpd_cup_h=2;
$gpd_sph_r=7;
$flats = 1;
$hub_l = 1;
$hub_radius = 4;Basic Structure
the model consists of a flat base which will go under the atreus:
cube([$stand_width,
$atreus_bottom_length,
$flats]);a hook which will brace against the front of the keyboard:
rotate([0,0,$atreus_hook_angle])
cube([$stand_width,
$flats,
$atreus_hook_height]);a flat riser goes up the back of the model:
translate([0, $atreus_bottom_length, 0])
cube([$stand_width, $flats, $riser_height]);an angled edge is designed to fit between the rubber feet of the GPD, rotated slightly for balance and with cups which the rubber feet can settle in to, and then a cut to keep the Y axis flat.
$riser_rotate_translation =
tan($gpd_rotate_down) * $gpd_canti_offset;
translate([0,
$atreus_bottom_length-$gpd_canti_offset,
$riser_height-$riser_rotate_translation-0.2]) {
rotate([$gpd_rotate_down, 0, 0]) {
intersection() {
translate([0,-2*$gpd_sph_r,-2*$flats])
cube([$stand_width*2,
$gpd_canti_length+4*($gpd_sph_r),
$flats*4]);
union() {
translate([$stand_width/2, -1*$gpd_cup_r,$flats]) rotate([0,180,0]) cup();
cube([$stand_width,
$gpd_canti_length,
$flats]);
translate([$stand_width/2, $gpd_canti_length+$gpd_cup_r,$flats]) rotate([0,180,0]) cup();
}
}
}
}LEGO compatibility
Bring in the paulirotta/PELA-blocks module which gives an auto-generator for cross-axle hubs; this is not tangled in to the assemblage at the end of this doc, but applied at the top level.
include <PELA-blocks/style.scad>
include <PELA-blocks/material.scad>
use <PELA-blocks/PELA-block.scad>
use <PELA-blocks/axle/PELA-technic-hub.scad>These will be used as crossbraces and a way to build a mounting system for battery, USB-C hub, etc.
_cut_line = 0;
_material = 0;
_large_nozzle = true;
_axle_radius = 2.3; // [0.1:1:20]
_center_radius = 0.83; // [0.1:0.01:4]
_axle_rounding = 0.73; // [0.2:0.01:4.0]
translate([0,
$atreus_bottom_length+$hub_radius,
$hub_radius])
rotate([45,0,0])
rotate([0,90,0])
hub(material=_material, large_nozzle=_large_nozzle, hub_l=$hub_l, hub_radius=$hub_radius, axle_rounding=_axle_rounding, axle_radius=_axle_radius, center_radius=_center_radius);
translate([0,
$atreus_bottom_length+$hub_radius,
$riser_height-$hub_radius+1.1])
rotate([45,0,0])
rotate([0,90,0])
hub(material=_material, large_nozzle=_large_nozzle, hub_l=$hub_l, hub_radius=$hub_radius, axle_rounding=_axle_rounding, axle_radius=_axle_radius, center_radius=_center_radius);Reinforced corners
This laptop is light but it isn't featherweight.
The bottom of the riser:
translate([0, $atreus_bottom_length, 0])
rotate([-90,0,0])
rotate([0,90,0])
difference() {
cylinder(r=3, h=$stand_width);
translate([-3,0,-3])
cube([3*3,3,3*3]);
}top of the riser
// tan($gpd_rotate_down)
translate([0, $atreus_bottom_length, $riser_height+0.2])
rotate([90,0,0])
rotate([0,90,0])
difference() {
cylinder(r=3, h=$stand_width);
translate([-3,0,-3])
cube([3*3,3,3*3]);
}Cups which the GPD feet can settle in to
Linked from
State "DONE" from "INPROGRESS"
State "INPROGRESS" from "NEXT"
the rubber feet are r=5mm h=2mm appear to be a slice of a sphere rather than a dome.
I did some trig that I am not quite certain of[fn:2]. modules have to be defined at the top level, this is not tangled in but put outside the assemblage below.
module cup() {
translate([0,0,-1*($gpd_sph_r-$gpd_cup_h)])
intersection() {
difference() {
sphere(r=$gpd_sph_r+$flats);
sphere(r=$gpd_sph_r);
}
translate([0,0,$gpd_sph_r-$gpd_cup_h])
cylinder(r=$gpd_sph_r, h=$gpd_cup_h+$flats);
};
};NEXT test print
NEXT add a base for counterweighting
plan to use my big anker usb-c powerpack here.
NEXT mounting design for USB-C hub
minimal cord lengths, clipped to the frame itself.
USB C or 2A for Keyboardio Atreus
USB 2A likely for atreus with trackball
USB-C to USB-C power routing
HDMI or display port (though USB-C to a display is probably preferable?)
NEXT simplify and document wire routing
NEXT elastic tie-down solution for safety
not sure how to do the atreus; add magnets?
Assemble it
All of the rest of the code is merged in to a single geometry using union and exported along with those parameters for OpenSCAD to render.
union () {
<<stand>>
}Footnotes
[fn:1] I want to figure out how to make make GPD Pocket Thumbtyping easier GPD Pocket Projects
[fn:2] http://blog.zacharyabel.com/2012/01/slicing-spheres/