equipment
Electronic Load Molecule
Public Made by Adomby adom
Siglent SDL1020X-E electronic load equipment prototype: reconstructed carrier STEP/GLB, constant-current dashboard, serial-pinned SCPI driver, control-panel integration guide and purchase budget.
main
12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758
"""Parametric planning reconstruction, not manufacturer CAD or fabrication approval.
Coordinates mm: X width, Y rearward, Z up. GLB meters, native Z-up for Adom.
"""
from pathlib import Path
import json
import cadquery as cq
import trimesh
import numpy as np
ROOT=Path(__file__).resolve().parents[1]
OUT=ROOT/'3d-boards'; OUT.mkdir(exist_ok=True)
parts=[]
def box(name,size,center,color):
s=cq.Workplane('XY').box(*size).translate(center).val();parts.append((name,s,color));return s
def cyl(name,r,h,center,color,axis='z'):
s=cq.Workplane('XY').circle(r).extrude(h).val()
if axis=='y':s=s.rotate((0,0,0),(1,0,0),90)
s=s.translate(center);parts.append((name,s,color));return s
# Instrument envelope includes feet/projections: keep reconstructed features inside documented limits.
box('instrument_housing_estimated',(246,392,101),(144,220,82.5),(0.77,0.79,0.80))
box('front_bezel_estimated',(256,12,108),(144,20,82),(0.91,0.92,0.91))
box('rear_bezel_estimated',(250,6,103),(144,419,82),(0.3,0.32,0.34))
box('display_estimated',(96,1,59),(85,13.5,88),(0.015,0.04,0.065))
for i in range(3):
for j in range(4):box(f'key_{i}_{j}',(11,2,7),(168+j*17,13,103-i*12),(0.22,0.25,0.28))
cyl('encoder_estimated',12,5,(222,17,61),(0.4,0.43,0.45),'y')
for name,x,color in [('positive',87,(0.85,0.1,0.08)),('negative',118,(0.08,0.09,0.1))]:cyl('terminal_'+name+'_estimated',6,10,(x,24,45),color,'y')
for x in [45,243]:
for y in [49,389]:box('foot_estimated_'+str(x)+'_'+str(y),(18,22,7),(x,y,28.5),(0.08,0.09,0.1))
# Envelope height is 115 mm from feet at Z25 to bezel at Z140.
parts=[(n,sh.translate((0,0,4)) if not n.startswith('foot_') else sh,c) for n,sh,c in parts]
# Independent support plate avoids treating scaffold PCB sockets as weight-rated fasteners.
plate=cq.Workplane('XY').box(288,448,4).translate((144,224,12))
for x in [16,272]:
for y in [16,432]:plate=plate.cut(cq.Workplane('XY').center(x,y).circle(2).extrude(20))
parts.append(('carrier_plate_concept',plate.val(),(0.2,0.55,0.56)))
for x in [7,281]:box('retaining_rail_concept_'+str(x),(4,400,14),(x,224,21),(0.2,0.55,0.56))
for x in [28,260]:
for y in [60,388]:box('support_pad_concept_'+str(x)+'_'+str(y),(28,28,10),(x,y,5),(0.16,0.18,0.20))
# Pin datum markers only: real pin STEP retained separately; no invented pin mating geometry.
for x in [16,272]:
for y in [16,432]:cyl('datum_marker_nonphysical_'+str(x)+'_'+str(y),2,2,(x,y,14),(1,0.65,0.1))
a=cq.Assembly(name='SDL1020X-E_carrier_PLANNING')
scene=trimesh.Scene()
for name,s,col in parts:
a.add(s,name=name,color=cq.Color(*col))
v,f=s.tessellate(0.3)
m=trimesh.Trimesh(vertices=np.array([p.toTuple() for p in v])*0.001,faces=np.array(f),process=False)
m.visual.vertex_colors=np.tile(np.array([*col,1])*255,(len(v),1)).astype('uint8')
scene.add_geometry(m,node_name=name,geom_name=name)
a.export(str(OUT/'electronic-load-carrier.step'))
scene.export(str(OUT/'electronic-load-carrier.glb'))
# Portable mesh geometry lets the dashboard display the same actual generated model.
meshes=[]
for n,g in scene.geometry.items():meshes.append({'name':n,'positions':g.vertices.flatten().tolist(),'indices':g.faces.flatten().tolist(),'color':g.visual.vertex_colors[0,:3].astype(float).tolist()})
(OUT/'preview.json').write_text(json.dumps(meshes,separators=(',',':')))
meta={'status':'planning reconstruction; not fit-verified','manufacturer':'Siglent','model':'SDL1020X-E','documented_envelope_mm':{'width':256,'depth':410,'height':115},'mass_kg':5.8,'carrier_mm':[288,448,4],'datum_mm':[[16,16],[272,16],[16,432],[272,432]],'datum_pitch_mm':[256,416],'units_step':'mm','units_glb':'m','up_axis':'Z (Adom native)','unverified':['connector centers','feet positions','vent keepouts','pin retention design','support-to-alignment-sheet interface','robot gripper and payload','thermal clearances'],'source':'https://siglentna.com/download/8733/'}
(OUT/'provenance.json').write_text(json.dumps(meta,indent=2))
print('Generated',len(parts),'named bodies. Planning assets only.')