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

275 lines
9.6 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 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](docs/BUILD_NOTES.md) for the full BOM, dew heater sizing table, and step-by-step assembly instructions.
See [docs/wiring-diagram.svg](docs/wiring-diagram.svg) for the colour-coded wiring diagram.
---
## Quick-start
### 1 Configure the firmware
Edit `firmware/src/config.h`:
```cpp
#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
```bash
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+](https://ascom-standards.org/Downloads/Index.htm) and [ASCOM Remote](https://github.com/ASCOMInitiative/ASCOM.Remote/releases).
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
```bash
# 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.
```bash
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`<br>`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`
```bash
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](docs/system-diagram.svg) | Architecture block diagram |
| [docs/wiring-diagram.svg](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.