← Home

Pergolux Wind Guard: hacking a pergola with ESP32 and Claude

The problem

I have a Pergolux bioclimatic pergola with motorized slats. It’s one of those pergolas with adjustable louvers that open and close to manage sun and rain. The motor is controlled by a 433MHz remote — model PX140-D&C, made by A-OK Technology. No app. No API. No home automation integration. Just a remote with four buttons.

The problem is wind. When a strong gust hits with the slats open, they rattle and take mechanical stress. Ideally, a system would monitor the weather and automatically close the slats when wind exceeds a certain threshold. But Pergolux offers nothing of the sort — the system is designed to be manual.

So I decided to build one myself.

The shopping list

The bill of materials was surprisingly short:

  • ESP32 DevKit v1 — microcontroller with built-in WiFi, the brain of the system
  • CC1101 E07-M1101D-SMA V2.0 — 433MHz radio module with SMA antenna, to speak the same language as the remote
  • Breadboard and jumper wires — for prototyping

Total cost: about 15-20 euros. The beauty of open source hardware.

The hardware

The connection is standard SPI between ESP32 and CC1101: seven wires between the two modules. VCC, GND, then MOSI, MISO, SCK, CSN and GDO0 — the pin the ESP32 uses to directly control radio transmission.

The moment I first plugged in the USB cable:

“ho attacato l’usb”

That moment when the ESP32 LED lights up is always when the project becomes real. Before that, it’s theory. After, it’s a device.

ESP32 connected to the CC1101 module via breadboard

Reverse engineering the RF protocol

This was the most interesting part. The Pergolux remote uses the proprietary A-OK protocol: 65-bit frames with OOK/ASK modulation, an AGC preamble, and no rolling code. Each transmission consists of 8 repetitions of the same frame, for a total duration of about 520 milliseconds.

The encoding is tri-state: each bit is represented by two pulses of different duration — 270 microseconds and 565 microseconds, alternating depending on whether the bit is 0 or 1. The frame contains a fixed remote ID (24 bits), a channel address (16 bits), the command (8 bits) and a checksum.

The process was iterative. First, signal capture with the CC1101 in receive mode, then pattern analysis with Python scripts, then protocol identification through FCC reports and a GitHub repository documenting the A-OK standard.

At one point, I had this key insight that I shared with Claude — the original remote’s stop command worked perfectly, so the RF signal had to be correct. The problem was in the software, not the protocol:

“no il telecomando funzionava benissimo lo stop, scusa ma se ho cliccato apri tre volte e poi stop e ha funzionato il segnale è giusto ma sicuro non sia lo stato?”

Sometimes the answer is simpler than you think.

The software

Once the RF protocol was working, I built the complete system on the ESP32 firmware:

A web server for manual control — five buttons to open, close, stop the slats and control the LED lights. Connection to Open-Meteo weather APIs to monitor wind, gusts and rain in Monterotondo every five minutes. An automatic protection system with hysteresis: close the slats when gusts exceed 40 km/h or rain exceeds 0.5mm, reopen when wind drops below 25 km/h. DuckDNS for remote access, Telegram notifications to know what the system is doing, and OTA updates so I don’t have to disassemble the ESP32 every time I modify the firmware.

The web interface was up, but something wasn’t right:

“il web server lo vedo, ma se clicco meno luce, non fa nulla e neanche se apro e chiudo la pergola”

“quello che noto io è che il web server sembra sempre reattivo, ma i comandi no”

Two observations that led me to the main issue: the web server was responding, but RF commands weren’t being executed. The reason? Network calls (weather fetch, Telegram send, DuckDNS update) were blocking the main loop, and RF signals — which require microsecond-precise timing — couldn’t be transmitted while the processor was busy with WiFi.

Then came an architectural insight that simplified everything — just send the signal, don’t track state:

“ma secondo me non ha senso tenere nessuno stato e mandare solo i segnali al click”

Less state, fewer bugs.

The debugging

Debugging was the most educational part — and the most frustrating.

This is how the debugging session with Claude started:

“controlla questo progetto, poi abbiamo due bug, quando la pergola si apre o si chiude lo stop non sembra funzionare sempre”

Two bugs: stop didn’t always work, and the lights had a stepped intensity system instead of simple on/off.

The bugs were intermittent — the worst kind:

“ho provato dal cell e ora va, secondo me è lo stesso bug dello stop”

“cmq certe volte stop funziona”

Works three times, then the fourth it doesn’t. Without a clear pattern, it’s easy to get lost in hypotheses. I pushed back on speculation:

“io direi di trovare un modo per testare le tue ipotesi, altrimenti stiamo qui ad ipotizzare”

“ma dei log non ti aiuterebbero?”

In the end, the problem was blocking I/O: blocking HTTP calls in the main loop prevented RF transmission at the right moment. The solution was to move RF commands to a queue and execute them in the main loop context, outside WiFi interrupts. 70 unit tests written to cover all cases — manual, automatic, hysteresis, cooldown, real-world scenarios.

The desk setup during debugging

Collaborating with an AI

At one point, I asked Claude to help me document the whole project:

“voglio scrivere un articolo linkedin su come ho hackerato la pergola, rivedi codice, steps, commits e docs per generarlo”

This project was built in collaboration with Claude Code from start to finish. Not in the sense that the AI wrote the code and I copied it. In the sense that I had the problem, the physical pergola, the domain understanding — and Claude had the technical patterns, the libraries, the knowledge of RF protocols and embedded architecture.

The result was being able to tackle a completely new domain for me — embedded systems, radio protocols, microcontroller firmware — in a weekend. Twenty years of software experience, but I had never touched an ESP32 before this project. AI bridged the gap between “I can code” and “I can code this”.

It’s not that the AI did the hard work. The hard work was understanding why stop wasn’t working, isolating the blocking I/O problem, designing the protection system architecture. AI accelerated everything else — the boilerplate, PlatformIO syntax, Open-Meteo APIs, CC1101 configuration.

Reflection

AI is giving us opportunities we wouldn’t have had before. I’m not just talking about speed — I’m talking about accessibility. Domains that would have required weeks of study are now reachable in days. It’s a new way to frame problems, to reason about feasibility, to explore unknown territory with a safety net.

But every time I close a session with Claude, I’m left with an ambivalent feeling. Yes, I built something that works. Yes, I learned. But did I learn as much as I would have without the AI? Did I truly understand the OOK protocol timing, or did I just verify that the generated code worked?

The project was satisfying precisely because it required real understanding — not just prompts. But the line is thinning. And I wonder: in a world where AI can bridge any knowledge gap in real time, how important is it to maintain the ability to focus and think deeply?