flatpanel/README.md
Laurence c32f00a2be Initial release v1.1.0 — ESP32 automated telescope flat panel
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
2026-05-17 08:51:29 +01:00

9.6 KiB
Raw Permalink Blame History

ESP32 FlatPanel

An open-source automated telescope flat-field panel built around the Arduino Nano ESP32.
Controls LED brightness, a motorised cover, and a dew heater — all accessible from ASCOM, INDI, and a standalone desktop application.


Features

Feature Detail
LED brightness 8-bit PWM (0255) via logic-level MOSFET
Motorised cover MG995 servo rotates panel in/out of the telescope light path
Dew heater 12V resistive element, 0100% PWM — keeps the diffuser clear
WiFi mode Native ASCOM Alpaca REST API on port 11111; auto-discovered via mDNS and UDP broadcast
USB mode Alnitak serial protocol at 9600 baud — plug-and-play with N.I.N.A., SGPro, APT and indi_flipflat
Both simultaneously WiFi and USB are active at the same time in a single firmware build
ASCOM Use ASCOM Remote (free, official) — no custom COM driver required
INDI Custom indi_esp32_flatpanel driver with WiFi and USB connection modes
Desktop app Dark-themed PyQt6 controller for direct manual operation

Repository layout

flatpanel/
├── firmware/                   ESP32 firmware (PlatformIO / Arduino)
│   ├── platformio.ini
│   └── src/
│       ├── config.h            ← edit this first
│       └── main.cpp
├── indi-driver/                INDI driver (C++, Linux)
│   ├── CMakeLists.txt
│   ├── indi_esp32_flatpanel.h
│   ├── indi_esp32_flatpanel.cpp
│   └── indi_esp32_flatpanel.xml
├── controller/                 Python desktop controller (all platforms)
│   ├── flatpanel_controller.py
│   └── requirements.txt
├── docs/
│   ├── system-diagram.svg      Block diagram — open in any browser
│   ├── wiring-diagram.svg      Colour-coded wiring — open in any browser
│   └── BUILD_NOTES.md          Step-by-step assembly guide
├── WIRING.md                   Quick-reference wiring + BOM
├── README.md                   This file
└── CHANGELOG.md

Hardware required

Component Role Pin
Arduino Nano ESP32 Main controller
MG995 servo Cover open/close D9
IRLZ44N MOSFET × 2 LED brightness + dew heater D3, D5
LM2596 buck module 12V → 5V for ESP32 + servo
12V PSU ≥ 4A Powers everything
White LED strip 12V (Ra ≥ 90) Flat-field illumination
Frosted acrylic 3mm Light diffuser
Dew heater element 12V ~24Ω Anti-dew resistive heater
100Ω resistor × 2 MOSFET gate series
10kΩ resistor × 2 MOSFET gate pull-down

See docs/BUILD_NOTES.md for the full BOM, dew heater sizing table, and step-by-step assembly instructions.
See docs/wiring-diagram.svg for the colour-coded wiring diagram.


Quick-start

1 Configure the firmware

Edit firmware/src/config.h:

#define WIFI_SSID       "your_network"
#define WIFI_PASSWORD   "your_password"

// Tune to your mechanical stops after assembly:
#define SERVO_CLOSED    0     // panel in flat position
#define SERVO_OPEN      90    // panel clear of telescope

// Set false when using USB/Alnitak mode to keep the serial line clean:
#define SERIAL_DEBUG    true

2 Flash

cd flatpanel
pio run -t upload          # PlatformIO CLI
# or use the PlatformIO IDE extension in VS Code

3 Verify

Open a serial monitor at 9600 baud.
You should see the ESP32's IP address printed on boot.
Browse to:

http://esp32-flatpanel.local:11111/management/v1/configureddevices

Expected response contains "DeviceType":"CoverCalibrator".


Connection modes

WiFi — ASCOM Alpaca (no driver needed)

The ESP32 is an Alpaca server. Use ASCOM Remote as the bridge to ASCOM COM:

  1. Install ASCOM Platform 6.6+ and ASCOM Remote.
  2. In ASCOM Remote, add a CoverCalibrator device → host esp32-flatpanel.local, port 11111, device 0.
  3. In N.I.N.A. / SGPro / APT, choose ASCOM CoverCalibrator and select the ASCOM Remote device.

The ESP32 is also discovered automatically by software that supports Alpaca UDP discovery (N.I.N.A. 3+, Cartes du Ciel).

WiFi — INDI

# Build and install the custom driver (once)
cd flatpanel/indi-driver
cmake -B build -DCMAKE_INSTALL_PREFIX=/usr
cmake --build build -j$(nproc)
sudo cmake --install build

# Start (KStars/Ekos loads it automatically after install)
indiserver indi_esp32_flatpanel

In Ekos: select ESP32 FlatPanel, set Connection Mode to WiFi / Alpaca, enter the host and port.

USB — Alnitak (plug-and-play)

Set SERIAL_DEBUG false in config.h and reflash. Then connect via USB-C.

The firmware speaks the standard Alnitak protocol so existing software works without any driver:

Software Built-in support
N.I.N.A. Alnitak / Flip-Flat
Sequence Generator Pro Alnitak
Astro Photography Tool Alnitak
INDI (indi_flipflat) ships with INDI
Our INDI driver USB mode in Connection tab

Dew heater via USB: The standard Alnitak protocol has no dew heater concept.
Our INDI driver and the Python controller use custom extension commands >T (set) / >U (get) that are silently ignored by other software.

Desktop controller app

Works in both WiFi and USB mode. Dark-themed for night use.

pip install PyQt6 requests pyserial
python flatpanel/controller/flatpanel_controller.py

Alpaca API reference

Base URL: http://<host>:11111/api/v1/covercalibrator/0/

Method Endpoint Parameters Description
GET coverstate 2=Open, 3=Closed, 4=Moving
GET calibratorstate 1=Off, 3=Ready
GET brightness Current brightness 0255
GET maxbrightness Always 255
GET dewheater Current dew heater 0100% (custom)
PUT opencover Rotate panel out of light path
PUT closecover Rotate panel into flat position
PUT haltcover Stop cover movement
PUT calibratoron Brightness=N Turn on LED at brightness N
PUT calibratoroff Turn off LED
PUT dewheater Percentage=N Set dew heater 0100% (custom)
PUT action Action=SetDewHeater
Parameters=N
Alpaca-standard alternative to PUT dewheater
PUT action Action=GetDewHeater Returns current dew % as string Value

Management endpoints: /management/apiversions, /management/v1/description, /management/v1/configureddevices


Alnitak serial protocol reference

Port: USB-C at 9600 baud, 8N1.
Command format: >CXXX\r · Response format: *CDDVVV\r (DD = device type 19).

Cmd Description Example
>P000 Ping *P19000
>S000 State (motor + light) *S19 + motor(1) + light(0) + 00
>B128 Set brightness 0255 *B19128
>J000 Get brightness *J19128
>L000 Light on (keep current brightness) *L19000
>D000 Light off *D19000
>O000 Open cover *O19000
>C000 Close cover *C19000
>H000 Halt cover *H19000
>T050 Set dew heater 50% (custom) *T19050
>U000 Get dew heater % (custom) *U19050

Motor state in >S000 response: 0=unknown/moving · 1=closed · 2=open
Light state: 0=off · 1=on


Pin assignments

D-pin GPIO Function Config define
D9 MG995 servo signal SERVO_PIN
D3 LED MOSFET gate LED_PWM_PIN
D5 Dew heater MOSFET gate DEW_HEATER_PIN

All pins use the Arduino Nano ESP32 D-number scheme.
LEDC channel 0 → LED · channel 1 → dew heater.


Building the INDI driver

Dependencies: libindi-dev, libcurl4-openssl-dev, nlohmann-json3-dev, cmake

sudo apt install libindi-dev libcurl4-openssl-dev nlohmann-json3-dev cmake build-essential

cd flatpanel/indi-driver
cmake -B build -DCMAKE_INSTALL_PREFIX=/usr
cmake --build build -j$(nproc)
sudo cmake --install build

If nlohmann-json3-dev is unavailable, CMake will fetch it automatically via FetchContent.


Troubleshooting

Symptom Fix
No boot message on Serial Check VIN wiring; try USB-C direct to PC (bypasses LM2596)
Servo twitches constantly LM2596 sagging; re-measure 5V under servo load
LED stays on at 0% Missing 10kΩ gate pull-down on MOSFET-A
Alnitak commands ignored Set SERIAL_DEBUG false, reflash
Connection refused on port 11111 ESP32 not yet connected to WiFi; check credentials
Dew heater not warming Verify MOSFET-B drain voltage ≈ 0V when active; check element resistance
Python app import error pip install PyQt6 requests pyserial
INDI build fails sudo apt install libindi-dev

Diagrams

File Description
docs/system-diagram.svg Architecture block diagram
docs/wiring-diagram.svg Colour-coded wiring diagram

Open either file in a web browser — no additional software needed.


Licence

Released under the MIT Licence — see LICENCE file.
ASCOM and Alpaca are trademarks of the ASCOM Initiative.
INDI is maintained by the INDI developers at indilib.org.