Skip to content

Latest commit

 

History

19 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

ESP32 Rolloff Roof — ASCOM Alpaca Driver

An ESP32-based controller for a rolloff observatory roof driven by a garage door opener. Implements the ASCOM Alpaca Dome interface so any Alpaca-compatible astronomy application (N.I.N.A., Cartes du Ciel, etc.) can open, close, and monitor the roof. A built-in web page provides manual control from any browser on the local network.

Roof controller on the bench: round display showing CLOSED, ESP32 on a screw-terminal board, Phidgets SSR


How the roof is driven

This driver is built for a roll-off roof pulled by a standard garage door opener, controlled the same way its wall button controls it: a single momentary contact that both opens and closes. There is no separate open input and close input. Each press cycles the opener through its sequence — move, stop, move back — and the relay imitates one press with a 250 ms pulse on GPIO 18.

Everything unusual about the firmware follows from that one fact:

  • The device cannot command a direction. It can only say "press the button". It infers what the roof is doing from the last command it issued and the two limit switches.
  • AbortSlew pulses only while the roof is actually moving. On a toggle input, pressing the button on a stationary roof would start it, so an abort on a stopped roof deliberately does nothing.
  • Opening an already-open roof does nothing. The commands check the limit switches first, because a stray pulse would close it.
  • The two limit switches are the only ground truth. Between them the roof's position is unknown, which is why a 2-minute movement watchdog exists.

If your opener exposes separate open and close inputs, or accepts a position command, this firmware needs modification rather than configuration.


Features

  • ASCOM Alpaca Dome driver (IDomeV2, interface version 2) on port 11111
  • Alpaca UDP auto-discovery on port 32227 — no manual IP entry needed in N.I.N.A.
  • Browser control/status page on port 80, plus a diagnostics page at /diag
  • 1.28″ GC9A01 round TFT (240×240) showing shutter status, IP address and whether Alpaca is polling
  • Two limit switches (OPEN and CLOSED positions)
  • Relay pulse (250 ms) to toggle the motor controller
  • 2-minute movement watchdog — sets error state if a limit switch is never reached
  • WiFi credentials kept in a gitignored file — safe to push to GitHub

Reliability

The roof has to work unattended overnight, so several failure modes are handled explicitly:

  • Persistent HTTP connections on the Alpaca port. N.I.N.A. polls a dome several times a second. Arduino's WebServer closes the connection after every response, and lwIP holds each closed socket for about 140 seconds, so the device can only sustain roughly 7 new connections a minute. Port 11111 therefore runs on ESP-IDF's esp_http_server, which keeps the connection open — an entire session costs one connection instead of thousands. The status page reports requests per connection so you can confirm it.
  • Hardware task watchdog. The chip resets if loop() stops running.
  • WiFi supervisor. Notices a dropped association from driver events, re-associates, and reboots if it cannot recover. It never reboots while the roof is moving.
  • Poll-stall supervisor. Catches the failure the WiFi supervisor can't see: the association stays up, but traffic to this one device blackholes and the client's polls time out. (The RG-11 safety monitor lost N.I.N.A. this way twice in one night with nothing in its log.) Once a client has proved itself live — PUT Connected=true or a status poll — 35 s of silence on the Alpaca API logs polls stopped (link up), 70 s forces a re-association, and 10 min disarms so a N.I.N.A. that was simply closed doesn't cause reconnect flapping overnight. PUT Connected=false disarms immediately. The status page shows the last poll age and stall count, and the display's Alpaca:OK turns to Alpaca:-- after 30 s of silence.
  • Diagnostics that survive a reboot. Boots, WiFi drops with their 802.11 reason codes, roof commands, and poll stalls (with the outage length when polls resume) are logged to RTC memory, which outlives a watchdog reset. A power cycle clears it deliberately, so the counters always mean "since mains was applied".
  • The display is optional. The SPI link to the panel is write-only, so the firmware simply draws whether or not a display is plugged in. An IPS TFT does not burn in, so unlike the earlier OLED it needs no drift or idle-blank tricks.

Hardware

Part Description
ESP32 DevKit-C 38-pin, USB-C (ESP32-WROOM-32)
Display 1.28″ GC9A01 round TFT, 240×240, SPI, 7-pin header (VCC GND SCL SDA DC CS RST)
Limit switch ×2 Normally-open (NO) momentary switches
Relay module Phidgets 3054 SSR (500 mA, 40 VDC / 28 VAC), triggered by a logic-HIGH pulse. Its output wires across the garage door opener's wall-button terminals, in parallel with the existing button
Garage door opener Any opener driven by a single momentary contact that opens, stops, and closes in sequence

Phidgets 3054 solid-state relay: Control terminals from the ESP32, Load terminals to the opener's wall-button input


Wiring

ESP32 DevKit-C pin layout (USB-C end at top)

LEFT SIDE                              RIGHT SIDE
─────────────────────────────────      ─────────────────────────────
3V3  ── TFT VCC ┐                      VIN
GND  ── TFT GND │                      GND  Limit sw common (both)
D15  ── TFT SCL │ display header       D13
D2   ── TFT SDA │ seats directly on    D12
D4   ── TFT DC  │ these seven pins     D14
RX2  ── TFT CS  │                      D27
TX2  ── TFT RST ┘                      D26
D5                                     D25
D18 (GPIO18) ── Relay signal           D33 (GPIO33) ── Limit sw OPEN
D19                                    D32 (GPIO32) ── Limit sw CLOSED
D21                                    D35
RX0                                    D34
TX0                                    VN
D22                                    VP
D23                                    EN
GND  ── Relay GND

Wiring – GC9A01 display

The display seats directly onto the first seven pins of the left rail — no jumpers. Its header order matches the board silkscreen one-to-one, the same arrangement used on the RG-11 safety monitor.

The module labels its SPI pins with I²C names: SCL is SCK and SDA is MOSI. It is SPI, not I²C. There is no BLK pin, so the backlight is permanently on.

Display pin  →  ESP32 header pin  (GPIO)
──────────────────────────────────────────
VCC          →  3V3
GND          →  GND
SCL          →  D15              (GPIO 15, SCK)
SDA          →  D2               (GPIO 2,  MOSI)
DC           →  D4               (GPIO 4)
CS           →  RX2              (GPIO 16)
RST          →  TX2              (GPIO 17)

Pin numbers are set in platformio.ini as TFT_eSPI build flags, so no User_Setup.h edit is needed and the config travels with the repo. GPIO 2 also drives the DevKit's onboard LED, so it flickers with SPI traffic — harmless. GPIO 2 and 15 are strapping pins, but the display is a high-impedance input on those lines, so flashing and booting are unaffected.

Connection summary

ESP32 pin Signal Notes
GPIO 32 (D32) Limit switch — CLOSED Pull-up enabled; switch other terminal → GND
GPIO 33 (D33) Limit switch — OPEN Pull-up enabled; switch other terminal → GND
GPIO 18 (D18) Relay signal Pulses HIGH for 250 ms, imitating one press of the opener's wall button
GPIO 15 (D15) TFT SCL (SPI clock) Display seats on the first seven left-rail pins
GPIO 2 (D2) TFT SDA (SPI MOSI)
GPIO 4 (D4) TFT DC
GPIO 16 (RX2) TFT CS
GPIO 17 (TX2) TFT RST
3V3 TFT VCC
GND TFT GND, relay GND, switch common

The two limit-switch GPIOs (D32/D33) are adjacent on the right rail.


Software setup

1. Clone the repository

git clone https://github.com/exploded/ESP32-Rolloff.git
cd ESP32-Rolloff

2. Create your WiFi credentials file

cp include/wifi_credentials.h.example include/wifi_credentials.h

Edit include/wifi_credentials.h and fill in your SSID and password:

#define WIFI_SSID "YourSSID"
#define WIFI_PASS "YourPassword"

wifi_credentials.h is listed in .gitignore and will never be committed.

3. Build and flash

Open the project in PlatformIO (VS Code extension or CLI) and upload:

pio run --target upload

Required libraries (installed automatically by PlatformIO via platformio.ini):

  • bodmer/TFT_eSPI (configured by the build_flags block in platformio.ini)

Usage

Browser

Open http://<ESP32-IP>/ in any browser on the same network. The page shows shutter status, switch states, link health, and Open / Close buttons. It polls a small JSON endpoint every 10 seconds rather than reloading itself, so leaving a tab open costs the device very little.

http://<ESP32-IP>/diag shows the reset reason, boot count, and the event log described under Reliability.

Path Port Purpose
/ 80 Status and control page
/status.json 80 Status as JSON, polled by the page
/cmd?a=open|close|abort 80 Same-origin roof control used by the buttons
/diag 80 Diagnostics and event log
/api/v1/dome/0/… 11111 ASCOM Alpaca Dome API
/management/… 11111 Alpaca management API

Monitoring

scripts/monitor-rolloff.ps1 logs availability and the device's own counters to a CSV. It is read-only and cannot move the roof. Run it on the observatory PC and leave it going:

.\scripts\monitor-rolloff.ps1 -Ip <ESP32-IP>

It probes once a minute by design. Do not speed it up — a faster prober becomes a significant part of the load it is trying to measure.

ASCOM Alpaca (N.I.N.A., Cartes du Ciel, etc.)

The device advertises itself via Alpaca UDP discovery — most clients will find it automatically. If you need to enter it manually:

Setting Value
IP address assigned by your router (shown on the display)
Alpaca port 11111
Device type Dome
Device number 0

Serial monitor

Connect at 115200 baud to see startup messages including the assigned IP address.


Display

The round panel uses the same scheme as the RG-11 safety monitor, so the two read alike side by side: a coloured ring at the rim around a black centre.

        ╭───────────────╮
      ╭─┤    coloured   ├─╮      ring + headline colour:
     ╱  ╰───────────────╯  ╲       green  OPEN
    │         OPEN          │      blue   CLOSED
    │     192.168.1.38      │      amber  OPENING / CLOSING
    │   Alpaca:OK  T:1234   │      red    ERROR
     ╲   -62dBm  up 318m   ╱
      ╰───────────────────╯
Line Meaning
Headline Shutter status: OPEN / CLOSED / OPENING / CLOSING / ERROR
IP address Or WiFi lost 42s while the supervisor is reconnecting
Alpaca:OK / Alpaca:-- A client polled port 11111 within the last 30 s — shows on the wall when N.I.N.A.'s polls stop reaching the device. T: is the Alpaca request count since boot
Footer WiFi RSSI and uptime in minutes

The whole frame is drawn into an off-screen sprite and pushed in one go, so it refreshes twice a second without flicker. Boot progress (WiFi connecting..., WiFi FAILED, Restarting) is shown as a two-line message.


Ports

Port Protocol Purpose
80 TCP/HTTP Browser status + control page
11111 TCP/HTTP ASCOM Alpaca Dome API
32227 UDP Alpaca auto-discovery

GPIO summary

GPIO Direction Function
2 Output TFT SDA (SPI MOSI) — also the onboard LED
4 Output TFT DC
15 Output TFT SCL (SPI clock)
16 Output TFT CS
17 Output TFT RST
18 Output Relay pulse (HIGH = active)
32 Input Limit switch CLOSED (active LOW)
33 Input Limit switch OPEN (active LOW)

About

ESP32 Arduino ASCOM Alpaca dome driver for a rolloff observatory roof, with SSD1306 OLED display

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages