Project: Pool Control Upgrade

When we bought our house, we were excited that it came with a pool. Several years and several dollars in upkeep later, it’s still pretty nice to have a cool oasis in the summer Georgia heat. Unfortunately, the controller is failing and that cool, crystal clear water can turn into a swamp fast when the filter pump just … stops working.

The Problem

Our pool has an Aqualink controller with a bunch of sweet bells and whistles that don’t work anymore. The local control panel is unresponsive and Aqualink PDA has seen a few too many hot summer days. The LCD screen is blank most days and it eats batteries faster than I can change them. So, what does an engineer with laughably little leisure time do? Dream of building my own controller of course! And maybe I’ll get around to implementing it too.

The Options

  • Upgrade Aqualink: Jandy still makes Aqualink gear and for the price of a janky car I could have the latest and greatest proprietary gear delivered to my door.
    • Pro: Support! Jandy maintains a hotline and the internet has lots of documentation out there. If I get hit by a bus, my wife can call a number and have The Pool Guy take over with minimal learning curve.
    • Pro: Exists! This solution exists and just needs a credit card to order.
    • Pro: OTS Spares! When Murphy (or lightning) strikes, drop-in replacement parts are only a web order away.
    • Pro: Remote Control! Aqualink has their PDA or an app available.
    • Con: Proprietary App! Aqualink’s phone app probably sends analytics (at minimum) to some data center God knows where.
    • Con: Expensive! Expletively expensive even, to my penny pinching standards. In an age where I can talk to my dad, watch a cat video, and compose this post from almost anywhere in the world for less than $200, it seems outrageous that an RF enable handheld with poor range and crappy response time is over $1,000 and that doesn’t include the local controls.
  • Dumb it down: I could rip all this newfangled push-button remote control nonsense out and just use the local breakers and switches. This works, but who wants to fiddle in a panel box with wet hands or traipse across the yard after a cold-weather spa session?
    • Pro: Cheap! Each piece of equipment has a breaker, on/off switch, or selector switch anyway, so this is just using the existing controls.
    • Pro: Simple! It doesn’t get more complicated than on/off.
    • Con: Simple! It CAN’T get more complicated than on/off, which is not ideal for the heater controlling spa temperature.
    • Con: Local Control Only! The pool equipment is on the backside of the pool, across a grass and dirt span, which could be uncomfortable on a cold day after a hot spa or with wet feet making muddy footprints. Also, electric breakers and wet hands seem like a bad time.
  • Go Bespoke: I’ve dabbled with microcontrollers before on much smaller projects and this seems like a perfect way to spend more time and money than necessary to solve a minor inconvenience.
    • Pro: Cheap! While not as cheap as it used to be, eBay has every electronic component Asia has to offer available in quantity for less than the cost of my daily caffeine habit.
    • Pro: Open Source! Thanks to the Internet and the open-source community, almost all of the code or scripting is available for use online for free.
    • Pro: Remote Control! Using free tools, I can set up a simple webpage accessible from my home network that allows anyone with the password to login and control the pool, beit from a phone or laptop. Open source phone apps can tie in as well.
    • Pro: Self-Hosted! All data will go to my own machine on my own network, that way only I see it. [Citation needed]
    • Con: Complicated! I better document the duck out of this, otherwise my wife will be in a pickle if I get hit by a bus.
    • Con: Custom! Hopefully everything works right the first time and nothing bad happens without a spare part on the shelf. Local controls will still work but that defeats the purpose.

Writing all this up, the expensive Aqualink proprietary solution makes a strong argument from a convienience and continuity perspective (please watch for speeding buses). But that’s no fun and (probably) somebody else’s problem1. So let’s Go Bespoke and explore a custom controls system.

The Plan

Initial searches online yield a few stale Github repos using RaspberryPis and a relay hat, which is nice. I have a spare Pi or three in my shop and have tinkered with them enough to be comfortable. I spent several hours fighting insomnia chasing this RPi path before I remembered we live in an age of Literal Logical Magic. 20 minutes on ChatGPT and I have a solid action plan in order that seems as good a starting point as any:

### Step-by-Step Summary for Pool Control System Project

This project aims to replace a faulty Jandy Aqualink PDA with a system that uses an ESP32 microcontroller to control pool equipment via both local physical buttons and a web interface. The system will be installed outdoors, requiring robust protection against the elements.

#### Components and Setup

1. **ESP32 Dev Board:**
   - Recommended: ESP32-WROOM-32 Dev Board.
   - Protection: Use a weatherproof and waterproof enclosure (IP65 or higher).

2. **Enclosure:**
   - Use a durable material like ABS plastic or polycarbonate.
   - Ensure the enclosure has adequate ventilation and includes silica gel packets to control humidity.

3. **Power Supply:**
   - Use a waterproof power supply rated for outdoor use.
   - Consider a battery backup.

4. **Connections:**
   - Use waterproof connectors or seal connections with silicone or epoxy.

5. **Mounting:**
   - Securely mount the enclosure in a location that avoids extreme conditions like direct sunlight or standing water.

#### Simplified and Durable Design

- **Microcontroller:** ESP32 with built-in Wi-Fi for local and web control.
- **Relay Module:** To control pumps, heater, and valves.
- **Push Buttons and LEDs:** For local control and status indication.
- **Software:** Use MicroPython to run a web server and handle button presses.

#### Complete Code with Comments

```python
import machine
import network
import time
import uasyncio as asyncio
from machine import Pin

# Define GPIO pins for relays, buttons, and LEDs
devices = {
    "pump1": {"led": 17, "button": 18, "relay": 27},
    "pump2": {"led": 22, "button": 23, "relay": 10},
    "heater": {"led": 24, "button": 25, "relay": 9},
    "valve1": {"led": 5, "button": 6, "relay": 11},
    "valve2": {"led": 12, "button": 13, "relay": 8},
    "valve3": {"led": 19, "button": 20, "relay": 7},
    "all_stop": {"button": 21}  # Button for All Stop functionality
}

# Set up GPIO pins
for device, pins in devices.items():
    if "led" in pins:
        Pin(pins["led"], Pin.OUT).value(1)  # LED off
    if "button" in pins:
        Pin(pins["button"], Pin.IN, Pin.PULL_UP)
    if "relay" in pins:
        Pin(pins["relay"], Pin.OUT).value(1)  # Relay off

# Connect to Wi-Fi
ssid = 'your_ssid'
password = 'your_password'

def connect_wifi():
    wlan = network.WLAN(network.STA_IF)
    wlan.active(True)
    wlan.connect(ssid, password)
    while not wlan.isconnected():
        pass
    print('Network config:', wlan.ifconfig())

connect_wifi()

# Web server to display status and allow control via web interface
async def web_server():
    import uhttpd
    server = uhttpd.Server()
    @server.route('/')
    async def index(req, resp):
        await resp.start_html()
        await resp.send('<html><body><h1>Pool Control</h1>')
        for i, relay in enumerate(devices.values()):
            if "relay" in relay:
                status = 'ON' if Pin(relay["relay"]).value() == 0 else 'OFF'
                await resp.send(f'<p>Device {i+1}: {status}</p>')
        await resp.send('</body></html>')
    await server.start(port=80)
    print('Web server running')

# Callback function to handle button presses
def button_callback(pin):
    for device, pins in devices.items():
        if "button" in pins and pin == pins["button"]:
            relay = Pin(pins["relay"])
            led = Pin(pins["led"])
            if relay.value() == 1:  # If relay is off
                relay.value(0)  # Turn relay on
                led.value(0)  # Turn LED on
                print(f"{device} is ON")
            else:
                relay.value(1)  # Turn relay off
                led.value(1)  # Turn LED off
                print(f"{device} is OFF")

# Function to stop all devices
def stop_all_devices(pin):
    for device, pins in devices.items():
        if "relay" in pins:
            Pin(pins["relay"]).value(1)  # Turn all relays off
        if "led" in pins:
            Pin(pins["led"]).value(1)  # Turn all LEDs off
    print("All devices are OFF")

# Set up button interrupts
for device, pins in devices.items():
    if "button" in pins and device != "all_stop":
        Pin(pins["button"]).irq(trigger=Pin.IRQ_FALLING, handler=button_callback)
# Set up All Stop button interrupt
Pin(devices["all_stop"]["button"]).irq(trigger=Pin.IRQ_FALLING, handler=stop_all_devices)

# Main loop to run the web server
async def main():
    await web_server()
    while True:
        await asyncio.sleep(1)  # Keep the script running

asyncio.run(main())
```

### Summary

1. **Select an ESP32 dev board and protect it in a weatherproof enclosure.**
2. **Set up GPIO pins for relays, buttons, and LEDs.**
3. **Connect the ESP32 to Wi-Fi.**
4. **Implement a web server to allow web-based control and status monitoring.**
5. **Add button callbacks for local control, including an All Stop button to stop all devices.**
6. **Ensure the system is protected from environmental factors and has a stable power supply.**

By following these steps and using the provided code, you can create a durable and simplified pool control system with both local and web control capabilities.

I am not a Python expert, but I assume some modifications will be needed to the code. Already I can see that I want the local control panel LEDs to read the actual state rather than program state. Or maybe both would be nice.

I’ll update this post as the project progresses. Cheers!

  1. This is generally regarded as poor form and only included in jest. ↩︎

Project: Desk Clock – 01

The main components, courtesy of eBay sellers in the Far East

Today I’m beginning a new project: a desktop clock with a oled screen to tell time and temperature. This will be my first solo project. I have some basic Arduino and soldering experience thanks to an engineering course where my team and I built a mini sumo bot. We did not come in first place.

Design:

  • Primary – An OLED display will read the time and local temperature. Two push botton switchs will be installed to advice the hour and minute values to adjust for time change. Two AA batteries will give me a 3V power supply. A toggle power switch will kill the device to save battery if needed.
  • Secondary – If not too troublesome, the display will also add readouts for pressure and humidity. Blinkenlights will be added to alert if sudden pressure changes indicate possible weather events or failing that just to look cool

Parts List:

  • 2x AA Batteries
  • 1x Double AA battery holder
  • 1x Power toggle switch
  • 2x Push Button switch
  • 1x DS1302 clock module board
  • 1x BME280 atmospheric sensor board
  • 1x 0.96 inch 128×64 white OLED display
  • 1x Arduino Pro Mini, 3.3V version with an ATmega328
  • Lengths of wire to connect everything
  • Nylon standoffs to assemlbe the boards into a contiguous unit
  • Solderable breadboard

Procurement:

Most of the boards were sourced from the lowest unit cost seller on eBay. I began planning this project several months ago, but it took until today to finally receive all of the components.

The DS1302 comes pre-attached to a board with a coin cell battery. The Arduino Pro Mini requires a breakout board to program, so be sure to grab one (or three) of those as well. I wound up with three as the first one I ordered took nearly three months to arrive. I purchased two additional breakouts to avoid the long wait should the first one be dead on arrival. That said, eBay is your best friend so long as you don’t mind using knock off parts and you’re willing to buy more than one of each component.

Adafruit has arduino libraries for all of the modules. I imagine there will be considerable searching and hand wringing involved in making everything work together but this is a learning experience (for me) so that’s part of the “Fun“.

The Plan:

  1. Protoype wire up each component via SPI and breadboard. I am still new to SPI and I2C, but it seems like it is quite difficult to wire more than one distinct module via I2C
  2. Get each component to talk to the Arduino, this is where finding and parsing the Adafruit libraries comes in
  3. Clean up Arduino code and streamline, here I hope to take only the most relevant bits from Step 2 and rewrite the whole program from scratch. The 3.3V Pro Mini only has an 8Mhz processor so finding the right balance between polling the atmospheric sensor and clock will be vital
  4. Solder and screw the components together permanently, final assembly of the clock proper. I plan to solder the Arduino Mini to the breadboard to give me a better connection point for the standoffs, as well as provide mounting points once I have the printed case ready
  5. Design the case, once I have the final clock assembly, I can draw up an enclosure and have it printed. – OR – Build the case, once I have the final clock assembly, I can build a clear plexiglass enclosure because who doesn’t like seeing all the bits of their first creation

I fully anticipate deviations from The Plan, but I suppose that’s design for you.

TIL: Variable Resistors

104 would be 100,000 Ω or 100 kΩ

Today I learned how to interpret the values of trim pot resistors based on the printed text.

Back story: I recently found the wonderful world of cheap eBay electronics. This weekend I finally sat down with some trim pot variable resistors and learned that the 130 pieces I purchased were in separate bags for a reason. There are 13 different base resistance values … which I promptly mixed together in a fit of ignorance.

Fast forward to the internet and some searching and I now know how to interpret the three numbers printed on each. For example:

502: 50 x 10^2 or 50 x 100 or 5,000 Ohms
502 would be a 5 kΩ