Firmware (Arduino Nano ESP32 / PlatformIO): - Native ASCOM Alpaca CoverCalibrator REST API on port 11111 - Alnitak serial protocol on USB at 9600 baud (simultaneous with WiFi) - MG995 servo cover mechanism with non-blocking state machine (D9) - LED brightness PWM via IRLZ44N MOSFET, LEDC channel 0 (D3) - 12V dew heater PWM via IRLZ44N MOSFET, LEDC channel 1 (D5) - mDNS + UDP Alpaca discovery, WiFi watchdog reconnect - SERIAL_DEBUG flag to silence debug output in USB-only mode INDI driver (C++ / libcurl / nlohmann-json): - WiFi mode: HTTP Alpaca via libcurl - USB mode: Alnitak serial via POSIX termios - LightBoxInterface + DustCapInterface + dew heater number property Python controller (PyQt6): - Dark-themed desktop app for direct manual control - AlpacaBackend (requests) + AlnitakBackend (pyserial) - PollWorker QThread; cover, brightness, dew heater panels - QSettings persistence; auto serial port discovery Docs: - system-diagram.svg, wiring-diagram.svg (browser-renderable SVG) - BUILD_NOTES.md with BOM, LM2596 calibration, power-on checklist - WIRING.md quick-reference, README.md, CHANGELOG.md
11 KiB
ESP32 FlatPanel — Build Notes
Bill of Materials
| # | Item | Qty | Notes |
|---|---|---|---|
| 1 | Arduino Nano ESP32 | 1 | ESP32-S3 based, USB-C |
| 2 | MG995 servo | 1 | Cover open/close (D9) |
| 3 | SG90 micro servo | 1 | Spare / future use |
| 4 | 28BYJ-48 stepper | 1 | Spare / future use |
| 5 | IRLZ44N N-ch MOSFET | 2 | Logic-level; one for LED, one for dew heater |
| 6 | 100 Ω resistor ¼W | 2 | Gate series resistors |
| 7 | 10 kΩ resistor ¼W | 2 | Gate pull-downs |
| 8 | LM2596 buck converter module | 1 | 12V → 5V for ESP32 + servo |
| 9 | 12V DC power supply ≥ 4A | 1 | LED 2A + dew 0.5A + servo 1A peaks |
| 10 | White LED strip 12V (high-CRI ≥ Ra90) | 1 | Length to match aperture |
| 11 | Frosted acrylic sheet 3mm | 1 | Cut to telescope OD |
| 12 | Resistive heating tape / nichrome mat 12V | 1 | ~24 Ω for 6W; see sizing table below |
| 13 | Stripboard / perfboard | 1 | For wiring the MOSFETs and resistors |
| 14 | JST-XH connectors or screw terminals | set | For detachable wiring |
| 15 | Heat shrink tubing assorted | pack | For all soldered joints |
| 16 | Kapton tape 10mm | 1 roll | Securing heater element to acrylic |
| 17 | M2/M3 screws, standoffs | set | Mounting ESP32 and stripboard |
| 18 | 1N4007 diode (optional) | 1 | Reverse polarity protection on 12V input |
| 19 | Multimeter | 1 | Required for LM2596 calibration |
Dew heater element sizing
| Resistance | Power @ 12V | Suitable for |
|---|---|---|
| 48 Ω | 3 W | Refractor up to 80mm |
| 24 Ω | 6 W | Refractor 80–150mm (recommended starting point) |
| 16 Ω | 9 W | Newtonians 150–250mm |
| 12 Ω | 12 W | Large apertures 250mm+ |
PWM control means the average power is
P × (percent/100), so it is fine to overspec the element and run it at 30–50%.
Tools Required
- Soldering iron + solder (60/40 or lead-free)
- Wire strippers and cutters
- Multimeter (essential for LM2596 setup)
- Hot glue gun or epoxy (for mechanical parts)
- Small Phillips screwdriver
- Isopropyl alcohol + cotton swabs (flux cleanup)
- PlatformIO CLI or IDE for firmware flashing
Step-by-Step Build Instructions
Phase 1 — LM2596 Calibration ⚠ Do this FIRST before connecting anything else
- Connect only the 12V PSU to the LM2596
IN+andIN−terminals. - Set your multimeter to DC voltage, probes on
OUT+andOUT−. - Adjust the LM2596 trimmer pot (small brass screw):
- Clockwise → voltage increases
- Counter-clockwise → voltage decreases
- Dial to 5.00 V ± 0.05 V.
- Disconnect the PSU. The buck is now calibrated and safe to use with the ESP32 and servo.
Connecting the MG995 to an unregulated or high-voltage supply will burn out the servo electronics instantly.
Phase 2 — Stripboard Layout
Recommended wire colour convention:
| Colour | Rail |
|---|---|
| Red | 12 V positive |
| Orange | 5 V positive |
| Black | GND |
| Blue | PWM signal |
| Yellow | Servo signal |
| Grey | Load output (LED−, Heater−) |
Lay three horizontal bus strips along the top of the board:
12Vbus (red)5Vbus (orange)GNDbus (black)
Place both MOSFETs at the bottom edge of the board, flat faces to the right, legs bent 90° and inserted vertically:
IRLZ44N (flat face → you)
Pin 1: Gate ← 100Ω from ESP32 PWM, 10kΩ to GND
Pin 2: Drain → load negative (LED− or Heater−)
Pin 3: Source → GND bus
Phase 3 — MOSFET-A (LED Panel) Wiring
- Insert MOSFET-A into the stripboard.
- Solder a 100 Ω resistor between Gate and the pad that will connect to D3 on the ESP32.
- Solder a 10 kΩ resistor between Gate and the GND bus.
- Solder Source to the GND bus.
- Run a wire from Drain to the negative lead of the LED strip (mark it grey/black).
- Solder a wire from the positive lead of the LED strip to the 12V bus.
Test at this point: apply a 3.3V signal to D3 connection. The LED strip should illuminate. If it stays on at 0V, check the 10kΩ pull-down is correctly placed Gate→GND.
Phase 4 — MOSFET-B (Dew Heater) Wiring
Repeat Phase 3 for MOSFET-B, using D5 instead of D3, and the heating element instead of the LED strip.
The heater element positive lead connects to the 12V bus; negative to MOSFET-B drain.
Phase 5 — MG995 Servo Wiring
The MG995 uses a standard 3-wire connector:
| Wire colour | Connection |
|---|---|
| Brown or Black | GND bus |
| Red | 5V bus (from LM2596 — NOT 3.3V or raw 12V) |
| Orange or Yellow | D9 on ESP32 |
The MG995 draws up to 1A under load. Always power it from the regulated 5V rail. If the servo twitches or buzzes after connecting, re-check the LM2596 output voltage — it should not drop below 4.8V under servo load.
Phase 6 — ESP32 Power and Ground
- Run a wire from the 5V bus to VIN on the Arduino Nano ESP32.
- Run a wire from the GND bus to GND on the ESP32.
- Do not power the ESP32 from the 3.3V pin — that is an output, not an input.
Phase 7 — Firmware Configuration and Flash
- Open
firmware/src/config.hand edit:#define WIFI_SSID "your_network_name" #define WIFI_PASSWORD "your_password" - Tune servo angles (power the servo and watch physical movement):
#define SERVO_CLOSED 0 // panel in flat position #define SERVO_OPEN 90 // panel clear of telescope - For USB-only operation (no WiFi debug output on the serial line):
#define SERIAL_DEBUG false - Flash via PlatformIO:
cd flatpanel pio run -t upload
Phase 8 — First Power-On Checks (ordered sequence)
Work through this list in order. Stop if any step fails.
Step 1 — Bench test buck converter
- Measure 5V bus at LM2596 OUT+ with no loads connected.
- Must read 4.9–5.1V. Adjust if needed.
Step 2 — ESP32 power
- Connect ESP32 to 5V bus and GND bus only.
- Open a serial monitor at 9600 baud. You should see the boot message and a WiFi IP address printed.
- If nothing appears: check VIN wiring.
Step 3 — WiFi / Alpaca API verification
- Open a web browser and navigate to:
http://<IP>:11111/management/v1/configureddevices - You should see a JSON response including
"DeviceType":"CoverCalibrator".
Step 4 — Servo test
- Using a serial terminal at 9600 baud, send:
>O000(open cover command) - You should hear the servo move and receive:
*O19000 - Send
>C000to close. AdjustSERVO_OPEN/SERVO_CLOSEDangles and reflash if needed.
Step 5 — LED panel test
- Send:
>B100then>L000 - The LED strip should light up at ~39% brightness.
- Measure the voltage at MOSFET-A Drain — it should be near 0V when the LED is on (the load pulls it low).
Step 6 — Dew heater test
- Send:
>T050(50% power) - Wait 30 seconds. The heater element should be noticeably warm to the touch.
- Send:
>T000to turn off.
Step 7 — Full integration test
- Launch
controller/flatpanel_controller.py(pip install PyQt6 requests pyserialfirst). - Connect in WiFi mode.
- Exercise all controls: cover, brightness slider, dew heater slider.
- Confirm the log shows successful commands and the status dots update.
Phase 9 — Mechanical Assembly
- Flat panel diffuser: cut the frosted acrylic to the outer diameter of your telescope tube. A friction fit or 3D-printed retaining ring works well.
- LED strip: arrange in a spiral or grid on the rear of the acrylic. Secure with the adhesive backing or a thin layer of silicone.
- Dew heater: run the heating element in a serpentine pattern across the face of the acrylic (the side facing the telescope). Secure with Kapton tape. Do not cover the diffuser surface with tape.
- Cover hinge: mount the MG995 so it rotates the panel into and out of the optical path. A 3D-printed bracket is the cleanest approach. Set
SERVO_CLOSEDso the panel seats flush against the scope aperture. - Enclosure: mount the ESP32, stripboard, and LM2596 in a weatherproof ABS enclosure on the focuser end of the scope. Use cable glands for the 12V input, USB-C, servo lead, and LED/heater wires.
Software Setup
Windows — ASCOM
- Download and install ASCOM Platform 6.6+.
- Download and install ASCOM Remote — the Alpaca bridge.
- In ASCOM Remote setup, add a new CoverCalibrator device:
- IP address:
esp32-flatpanel.local(or the IP from the serial monitor) - Port:
11111 - Device number:
0
- IP address:
- In your capture software (N.I.N.A., SGPro, APT), choose ASCOM CoverCalibrator and select the ASCOM Remote device.
Linux / Raspberry Pi — INDI
# Install dependencies
sudo apt install libindi-dev libcurl4-openssl-dev nlohmann-json3-dev cmake build-essential
# Build the custom INDI driver
cd flatpanel/indi-driver
cmake -B build -DCMAKE_INSTALL_PREFIX=/usr
cmake --build build -j$(nproc)
sudo cmake --install build
# Test standalone
indiserver indi_esp32_flatpanel
In KStars / Ekos:
- Profile Editor → add Aux device:
ESP32 FlatPanel - In the driver's Connection tab: select WiFi or USB mode, enter host/port or serial port.
FlatPanel Controller App (all platforms)
pip install PyQt6 requests pyserial
# Run
python flatpanel/controller/flatpanel_controller.py
- Select WiFi or USB mode with the radio buttons.
- WiFi: enter the ESP32's hostname or IP and port 11111.
- USB: pick the COM port from the dropdown (click ⟳ to refresh).
- Click Connect.
Troubleshooting
| Symptom | Likely cause | Fix |
|---|---|---|
| Servo twitches/buzzes constantly | 5V rail sags under load | Re-measure LM2596; verify 5V at servo connector under motion |
| LED stays on even at 0% | Gate pull-down missing | Solder 10kΩ Gate→GND on MOSFET-A |
| LED at wrong brightness or inverted | Firmware PWM inverted? | Check LED_PWM_PIN and LED_PWM_CHANNEL in config.h |
| No WiFi after flashing | Wrong SSID/password | Edit config.h, reflash |
Alnitak >P000 gets no response |
SERIAL_DEBUG true corrupts line |
Set false, reflash |
| Cover angle wrong | SERVO_OPEN/CLOSED values wrong | Tune in config.h, reflash |
| Dew heater not warming | R too high, or MOSFET-B wiring issue | Measure Drain voltage with heater on; should be near 0V |
| Python app can't find serial port | Driver not loaded (Windows) | Install CH340 or CP210x driver for ESP32 USB |
| Connection refused on port 11111 | ESP32 not on WiFi yet | Check serial monitor for boot messages |
| INDI driver build fails | Missing libindi headers | sudo apt install libindi-dev |
Revision History
| Version | Date | Change |
|---|---|---|
| 1.0 | 2026-05-17 | Initial release: WiFi/Alpaca, servo, LED PWM |
| 1.1 | 2026-05-17 | Added USB/Alnitak mode, 12V dew heater, Python controller app |