pawin.dev / OpenHome / Window Opener
← Back to portfolio

OpenHome Foundation · Open-source hardware

Sliding Window Opener

A belt-driven retrofit that motorises a sealed sliding window — no track access, nothing structural, still opens by hand if the power's off.

Designed by Pawin Jirasuntornsiri · Firmware MIT · Hardware CC BY 4.0

Status: working
1050 mm travel, auto-calibrated
ESP32 + TMC2209
<3 kgf breakaway, ~2× margin
~900 THB / $30
Installed assembly: motor and idler brackets mounted to the wall, belt running to a clamp on the window's stile

Retrofit, not a replacement

Nothing structural changes

The panel it was built for slides horizontally, hangs entirely from a sealed ceiling track with no access to the carriage inside, and has no bottom track or guide. That constraint shaped the whole design: nothing can be added inside the track, so all the hardware hangs off the jambs at either end and the panel is pulled by a GT2 belt clamped to its vertical stile.

The sealed track stays sealed, the panel is never removed or modified, the glass is not touched, and no part of the window is cut, drilled or replaced. The entire intervention is two brackets on the jambs and a clamp on the panel's stile. Both brackets can be bonded with VHB tape rather than screwed, if you'd rather not drill at all.

It also stays a normal window. The driver is left disabled when idle, so the panel still slides by hand with the same effort as before — assist mode picks up the nudge and takes over. Nothing is captive, nothing is geared, and there is no clutch to disengage. Take it all off again and you're left with an ordinary sliding window, which is rather the point: this is a weekend addition to a window you already have, not a renovation.

The opener installed in situ on a bedroom window
Installed, bedroom window, Bangkok.

How it works

Belt, two idlers, and a clamp

The motor mounts vertically to one jamb with its shaft pointing down. A 20T drive pulley sits under the housing; a 16T guide idler and a 20T tensioning idler set the belt path. At the far end, a printed bracket carries a 20T idler on a sliding carrier that provides the main tension adjustment.

The belt is a single open length. Both cut ends terminate in an aluminium GT2 clamp bolted to the panel's stile, so the clamp both joins the belt and is the thing that gets dragged. The loop lies in a horizontal plane with the belt's 6 mm width vertical, which keeps the whole mechanism inside a shallow band just above the panel.

Auto-calibration

Total travel is not hardcoded. On boot the device seeks the closed limit, backs off until the switch releases, creeps back on slowly and zeroes there, then repeats the same two-stage approach at the open end while counting steps. This sidesteps the microstepping question entirely — whatever mode the driver comes up in, the measured count is correct in those units.

The two-stage approach matters: a single fast pass bounces off the end stop, so splitting it into a fast approach, a backoff, then a slow creep at 200 steps/s means the panel is barely moving at contact — it stops on the switch instead of overshooting, and the trigger point becomes repeatable since it no longer depends on arrival momentum.

Detail of the motor bracket and drive pulley

Drift correction

On every normal arrival at the open limit, actual position is compared against stored travel. Under 10% difference, the stored value is silently updated; over 10%, it logs a warning and leaves it alone. Belt skips therefore heal themselves on the next full traverse.

Fit the tensioning idler last

The tensioning idler at the motor end is not part of building the motor unit — it exists purely to take up belt tension, so it's the very last thing that goes on, after the brackets are mounted, the belt is routed, and the clamp is bolted to the panel. It appears in the motor sequence below only so you can see where it lands.

Bill of materials

What you need

Electronics

ItemDetail
MCUESP32 DevKit, 30-pin (Node32s), micro-USB
Stepper driverBIGTREETECH TMC2209 v1.3 (110 mΩ RSENSE)
MotorNEMA17 42BYGH40
PSU24 V 2 A, 48 W
Buck converterLM2596 adjustable, set to 5.0 V
Bulk capacitor2200 µF 35 V across driver VS/GND
Limit switches2× MC-38 reed sensors, enclosed type, tape-mounted
Magnet1× MC-38 companion magnet, on the stile
Perfboard7 × 9 cm, point-to-point soldered

Mechanical

ItemDetailQty
Drive pulleyGT2 20T, 5 mm bore1
Guide idlerGT2 16T W6, 3 mm bore, with bearings1
Tensioning idlerGT2 20T, 3 mm bore, with bearings — belt tension only1
Far-end idlerGT2 20T W6, 3 mm bore, with bearings1
BeltGT2 6 mm carbon-reinforced, open length~2.5× window width
Belt clampGT2 aluminium timing belt clamp (printable, aluminium preferred)1
Tensioner screwM3, through the 3 mm bore bearing1
Idler axleM2.5 × 161
Machine screwsM3, assorted lengths, plus nuts and washers~14
Heat-set insertsM33
Wall fixingssuit your wall, 4 per bracket8
⚠ Fastener sizes — check before ordering

The STEP files were exported with placeholder fasteners from the CAD library, so they read as 6-32, 10-24, M2.5 and M5 in the geometry. Everything is actually M3, except the M2.5 far-end idler axle. The tensioning idler is an M3 screw through a 3 mm bore bearing — it is not an M5, whatever the STEP says.

Printed parts

PartEnvelopeNotes
Motor housing, main body45 × 68 × 37 mmcarries the motor and both idlers
Motor housing, cover45 × 68 × 12 mmcloses the top
VHB standoff block11 × 48 × 12 mmflat face for VHB mounting
Idler carrier16 × 30 × 27 mmslides to tension the belt
Idler base plate14 × 29 × 29 mm2× M3 heat-set inserts

PA6 if you're screwing the brackets to the wall — printed at a 70 °C chamber temperature with no warping. ABS or PETG is fine if you're mounting with VHB tape instead, since the load path is then adhesive rather than a screw pulling through the part. The VHB standoff block exists specifically so tape has a flat, properly sized face to bond to — without it, screws are sufficient but VHB is not.

Wiring

Four sub-circuits

Logic (ESP32 ↔ TMC2209 over UART), power distribution (PSU → driver and buck → ESP32), the motor coils, and the two limit switches.

Interconnect diagram: ESP32 to TMC2209 logic, power distribution, motor coils, and limit switches
Click to open the editable SVG.
FromTo
ESP32 TX2 (GPIO17)TMC2209 RX
ESP32 RX2 (GPIO16)TMC2209 TX
ESP32 D22 (GPIO22)TMC2209 STEP
ESP32 D23 (GPIO23)TMC2209 DIR
ESP32 D5 (GPIO5)TMC2209 EN (active LOW)
ESP32 D4 (GPIO4)TMC2209 DIAG (StallGuard)
ESP32 3V3 / GNDTMC2209 VIO / GND (the one beside VIO)
ESP32 D18 (GPIO18)MC-38 #1, closed end
ESP32 D19 (GPIO19)MC-38 #2, open end
PSU +24 V / −TMC2209 VS / GND (the one beside VS)
2200 µF capacross VS / GND
Buck OUT+ / OUT−ESP32 VIN / GND
Motorgreen → A1, black → A2, red → B1, blue → B2

Coil A = green + black, coil B = red + blue; verify ~1–5 Ω per pair. MS1, MS2 and CLK are deliberately left unconnected — on the v1.3 board RX and TX are broken out separately, so no external 1 kΩ resistor is needed. All connections are hardwired.

Driver current. The BTT TMC2209 v1.3 uses 110 mΩ RSENSE. Vref is set to 1.27 V, about 1.4 A RMS. Turning the pot clockwise reduces current.

⚠ Never unplug the motor while the driver is powered

Inductive kickback destroys TMC drivers, and this is the single most common way they die.

Assembly

Three sub-assemblies

Build the motor housing, the idler carrier, and the belt clamp separately, then install brackets, route the belt, and fit the tensioning idler last (see How it works).

*Fitted here so you can see where it lands — actually the last thing installed. See Fit the tensioning idler last. Shown as M5 in the CAD; it's an M3 through a 3 mm bore bearing.

⚠ Known CAD issues
  • The idler axle screw is modelled head-up in Pully Holder.step. It goes in from below — fit it head-down regardless of what the file shows.
  • The 16T idler and the M5 tensioner are unplaced in MotorHolder.step when opened on its own. Use Assembly.step as the reference for their positions.

Installation

Onto the window

With the three sub-assemblies built, this is where the mechanism actually goes onto the wall and the window. Motor unit on one jamb, idler bracket on the other, belt clamp on the panel's leading stile.

Plan view of the complete installation: motor unit on the left jamb, idler bracket on the right, belt clamp on the panel's stile
The complete installation. Motor unit on the left jamb, idler bracket on the right, belt clamp on the panel's leading stile.

Mounting

Both ends screw to the jambs with 4× M3 countersunk screws each, or bond with VHB using the standoff block. Fix the motor end first, then stretch the belt across and position the idler bracket so the carrier still has adjustment left in both directions.

Belt routing and length

Cut roughly 2.5× the window width. The belt leaves the drive pulley, runs the length of the opening, wraps the far idler, and comes back. Both cut ends go into the aluminium clamp, teeth meshed, and the clamp bolts to the panel stile.

Tensioning

Target 20–30 N. In practice: plucked, the belt should give a dull thud rather than a ring, and mid-span it should deflect 5–10 mm under light finger pressure. Adjust with the two M3 screws on the idler carrier. If that's not enough range, fit the tensioning idler at the motor end (motor unit step 7, "fit last" — see Assembly) and take up the rest there.

Re-check tension after the first few full cycles

A new belt beds in and drops tension, and low tension is the main cause of skipped teeth.

Limit switches

Two MC-38 enclosed reed switches, tape-mounted, one near each end of travel. A single magnet on the stile triggers both. Full positioning procedure in Commissioning below.

⚠ Order matters

The drive pulley has to go on the shaft before the cover, and the grub screws have to be tightened before the housing closes. Get this wrong and it comes apart again.

Commissioning

Power up and calibrate

⚠ Set the buck converter first

Set the buck converter output to 5.0 V before connecting the ESP32 — LM2596 modules ship at arbitrary voltages, frequently well above 5 V. Set Vref on the driver, flash the firmware, then power up. The device homes and calibrates itself, so the order beyond that doesn't matter much.

If it runs the wrong way, flip the Reverse direction switch in Home Assistant. It inverts the sign used throughout and triggers a recalibration, so nothing downstream needs changing.

Limit switches

Two MC-38 enclosed reed switches, tape-mounted, one near each end of travel, with a single magnet on the stile triggering both.

Position them by testing, not by measurement

Tape them on loosely, slide the panel by hand and watch the binary sensors in Home Assistant until each trips reliably a little before its hard stop. Then run a calibration and confirm the panel stops clean at both ends. Tape is deliberate — it means you can move one a centimetre and try again, which is far faster than trying to get it right on paper.

Whatever offset you land on, the magnet must fully release the switch within backoff_steps (currently 1200) or the slow confirming pass never re-triggers and homing stalls.

Tuning

ParameterValueNotes
run_speed2500exposed as a Home Assistant slider
home_speed1000fast homing pass
creep_speed200slow confirming pass
backoff_steps1200must exceed magnet/sensor hysteresis
accel / decel1500exposed as a slider

Home Assistant entities

cover.window with open / close / stop / position. Sliders for run speed and acceleration. Switches for obstruction stop, assist mode and direction reversal. Buttons to recalibrate and re-home. Diagnostics for position, measured travel and WiFi signal.

Known issues

What's not finished

⚠ StallGuard is not configured — the main outstanding task

DIAG is wired to GPIO4 and read as a plain binary sensor, and the handler stops the motor when it asserts, but SGTHRS has never been written, so it won't fire meaningfully. A uart: block exists (id tmc_uart, GPIO17/16, 115200) and is currently unused — it was added for exactly this. TCOOLTHRS needs to bracket the actual run speed, since StallGuard is unreliable at very low and very high speeds. Until this works there is no mid-travel obstruction protection at all, and the panel is heavy glass travelling past a windowsill.

Gotchas

Ideas not yet pursued

Downloads

Everything, to build your own

Full build guide, printable BOM, print settings, step-by-step assembly for all three sub-assemblies, installation, wiring, firmware and commissioning.
↓ Download PDF
3D models 11 files
Firmware 1 file
Build instructions 2 files

Designed by Pawin Jirasuntornsiri. Firmware MIT licence, hardware and documentation CC BY 4.0. Share it, remix it, sell it if you like — just say where it came from.