ESP8266 sprinkler and Vibe programming
I moved from San Francisco to Osijek this summer (2025). The move was smooth, but I’ll leave details for a different post.
As a first-time homeowner, I did a lot of renovations. For the past several weeks, I have noticed that the automated irrigation system is no longer reliable. The system uses a controller from Toro and their DC solenoid latching valves. The controller drains the battery quickly, and its internal clock drifts too much (a few hours per day). Instead of purchasing a new controller, I decided to get back into electronics and create my own controller.
I purchased a D1 mini controller, an L298N motor controller (to be used for the solenoids), and a basic Arduino starter kit. I also got a (very) cheap oscilloscope for less than 40 euros.
The idea was simple: create a REST endpoint to turn on the desired valve for a specified duration, have a way to stop it, and get the current state of the system. To make things more interested, I decided to offload coding to AI and see how much I’ll need to do. I decided to use Cursor for this task. Connection-wise, it was fairly straightforward, so I didn’t make a diagram— I just connected everything together.
The first prototype was fixed time program to ensure valves open correctly. I instructed Cursor to make a simple script, told it what pins should be powered on and for how long. Since it’s a latching solenoid, it means a positive pulse will turn on the valve, and a negative pulse will turn it off. I decided on 25ms pulse as the solenoid datasheet calls for a pulse between 10ms and 100ms. Then, I instructed Cursor to generate Makefile, which it did just fine.
With make upload
, my project was live!
Well done, Cursor.
The next phase was connecting it to the real solenoids and testing how it worked. Lo and behold, it worked just fine!
The next phase was a real test for Cursor. I wanted a simple REST service. I gave a detailed explanation about all the desired endpoints (status, turn on for a specified duration, and turn off). I also instructed Cursor to turn off valves on start-up, in case there was a power-loss. The code looked very good, except for the hardcoded Wi-Fi SSID and password. But, as far as I know, that’s a fairly common thing to do, so I accepted this suboptimal solution, but moved the credentials to a dedicated header file.
Again, to my surprise, everything worked fine except for the JSON response, which I fixed by hand (I could probably have prompted it, but I thought it would be faster this way). I also refactored the code a bit to make it cleaner and less repetitive.
The last task for Cursor was to create a simple web page to control the sprinkler system. With a short but clear instruction about what should be supported, Cursor generated a single HTML page with JavaScript and CSS that called the REST endpoints. That worked without any issues, and I was able to send commands from my laptop.
The final step was connecting everything together. I decided to gamble a bit and used Cat 6 cable to send 12V pulses to open the valves, even though the solenoid datasheet actually recommends using thicker wire for this purpose. connected, I sent a few commands to start the irrigation, and my grass practically gave me a standing ovation. Next up for me is enclosing everything in a 3D-printed case. But I need to actually get a 3D printer.
So, what is my takeaway? I would have been able to solve this problem without AI, but it would have taken me a few more hours, and the web page wouldn’t look as nice as it does. On the flip side, I learned very little from this experiment—I have not looked at the web page source code prior to writing this (for your information, it uses no framework), and it would be time-consuming to edit it without using AI. I inspected the Arduino code and made some minor refactors, but for the most part, it’s unfamiliar code. Those are some big trade-offs if we’re talking about production code (especially security-wise), but not so much for a hobby project. I continue to be cautiously optimistic about Gen AI.
Note: Since the code is almost all AI generated, I decided not to put it online. However, if you are intersted in the code, let me know and I’ll upload it.