Files
forgefirm/scripts/bench/pwm_hold.py
T
ScottW514 fb956971b7 LASER_PWM waveform gate PASSED - scope-verified on the physical pin
Direct PWMSAR duty steps with the machine in the locked state
(controller stopped, cnc disabled so steppers are unpowered, laser
latch locked, lid closed; laser_on_sampled stayed 0 throughout).
Measured on the pin: 25.0 us period / 40 kHz stable across the full
duty range; 50/25/75 percent confirmed visually; low end
cursor-measured 6.4 vs 6.3 percent commanded (PWMSAR=8), clean pulse.
Matches the register-level audit numbers (divider 13 x 127 counts).

Adds pwm_sweep.py / pwm_hold.py to the bench kit and records the two
remaining pre-live-fire gates (1-tick laser drop at underrun via the
stream path with FIRE observable under a locked latch; interlock
readback semantics) in BRINGUP.
2026-08-02 16:08:34 -04:00

25 lines
932 B
Python

#!/usr/bin/env python3
"""Hold LASER_PWM at one duty value for a measurement window, then restore.
Usage: pwm_hold.py [sar] [seconds] (defaults: 8, 30)"""
import mmap, struct, sys, time
PWM2_BASE = 0x02084000
SAR_OFF = 0x0C
sar = int(sys.argv[1]) if len(sys.argv) > 1 else 8
secs = int(sys.argv[2]) if len(sys.argv) > 2 else 30
with open('/dev/mem', 'r+b') as f:
m = mmap.mmap(f.fileno(), 4096, mmap.MAP_SHARED,
mmap.PROT_READ | mmap.PROT_WRITE, offset=PWM2_BASE)
sar0 = struct.unpack('<I', m[SAR_OFF:SAR_OFF + 4])[0]
m[SAR_OFF:SAR_OFF + 4] = struct.pack('<I', sar)
print('PWMSAR=%d held for %d s (was %d)...' % (sar, secs, sar0))
sys.stdout.flush()
time.sleep(secs)
m[SAR_OFF:SAR_OFF + 4] = struct.pack('<I', sar0)
print('restored PWMSAR=%d' % sar0)
with open('/sys/glowforge/cnc/laser_on_sampled') as s:
print('laser_on_sampled =', s.read().strip())
m.close()