Initial commit: rotary dial firmware on ESP32 device framework
This commit is contained in:
@@ -0,0 +1,99 @@
|
||||
# Rotary Dial
|
||||
|
||||
ESP32 firmware that reads a pulse-generating telephone rotary dial and publishes the dialled number to Home Assistant over MQTT.
|
||||
|
||||
Built on the [ESP32 Device Framework](../Device-Framework).
|
||||
|
||||
## How it works
|
||||
|
||||
A classic rotary telephone dial generates a burst of pulses as it returns to rest after each digit — one pulse for `1`, two for `2`, …, nine for `9`, ten for `0`. The firmware counts those pulses on a single GPIO pin and assembles digits into a string. When the user stops dialling (2.5 s silence), the complete number is published to MQTT.
|
||||
|
||||
Leading zeros are preserved: dialling `07` sends `"07"`, not `"7"`.
|
||||
|
||||
## Hardware
|
||||
|
||||
| Item | Details |
|
||||
|------|---------|
|
||||
| MCU | ESP32 (any variant) |
|
||||
| Dial | Pulse-generating rotary telephone dial |
|
||||
| Pulse pin | GPIO 4 (`DIAL_PIN` in `main.cpp`) |
|
||||
| Wiring | Pulse contact between GPIO 4 and GND. Pin uses `INPUT_PULLUP`. |
|
||||
|
||||
The pulse contact is normally open. As the dial returns it briefly shorts GPIO 4 to GND on each pulse — the rising edge (release) is what the interrupt counts.
|
||||
|
||||
If your dial's contact is normally closed instead, change the interrupt trigger in `setup()` from `RISING` to `FALLING`.
|
||||
|
||||
## Building and flashing
|
||||
|
||||
```bash
|
||||
# Build (S3 DevKit)
|
||||
pio run -e esp32-s3-devkitc-1
|
||||
|
||||
# Flash
|
||||
pio run -e esp32-s3-devkitc-1 --target upload
|
||||
|
||||
# Serial monitor (115200 baud)
|
||||
pio device monitor
|
||||
```
|
||||
|
||||
## First-time Wi-Fi setup
|
||||
|
||||
On first boot the device opens an access point named **Rotary-Dial**. Connect with any phone or laptop; a captive portal will appear.
|
||||
|
||||
1. Enter your Wi-Fi credentials.
|
||||
2. Optionally set the **Device hostname** (default: `rotary-dial`).
|
||||
3. Save. The device joins your network and restarts.
|
||||
|
||||
Reachable at `http://rotary-dial.local` or the IP shown in the serial monitor.
|
||||
|
||||
### Factory reset
|
||||
|
||||
Power-cycle or press EN **5 times in quick succession** (before boot completes). All settings are cleared and the device restarts into the Wi-Fi portal.
|
||||
|
||||
## Web UI
|
||||
|
||||
Browse to the device address to configure hostname, authentication, and MQTT.
|
||||
|
||||
## MQTT
|
||||
|
||||
### Topics
|
||||
|
||||
| Direction | Topic | Description |
|
||||
|-----------|-------|-------------|
|
||||
| Published | `<prefix>/dialed` | Complete dialled number as a string (not retained) |
|
||||
| Published | `<prefix>/status` | `online` on connect, `offline` as LWT (retained) |
|
||||
|
||||
Default prefix: `dial`
|
||||
|
||||
### Home Assistant
|
||||
|
||||
On MQTT connect the device publishes a discovery payload so HA automatically creates a **sensor** entity (`sensor.<hostname>_dialed_number`) that shows the last dialled number.
|
||||
|
||||
Example automation:
|
||||
|
||||
```yaml
|
||||
automation:
|
||||
- alias: Act on dialled number
|
||||
trigger:
|
||||
platform: mqtt
|
||||
topic: dial/dialed
|
||||
action:
|
||||
- choose:
|
||||
- conditions:
|
||||
- condition: template
|
||||
value_template: "{{ trigger.payload == '112' }}"
|
||||
sequence:
|
||||
- service: notify.mobile_app
|
||||
data:
|
||||
message: "Emergency number dialled!"
|
||||
```
|
||||
|
||||
## Timing constants
|
||||
|
||||
Adjust in `main.cpp` if your dial runs faster or slower than standard:
|
||||
|
||||
| Constant | Default | Description |
|
||||
|----------|---------|-------------|
|
||||
| `PULSE_DEBOUNCE_MS` | 15 ms | Minimum time between counted edges |
|
||||
| `INTER_PULSE_MS` | 350 ms | Silence after last pulse = digit complete |
|
||||
| `INTER_DIGIT_MS` | 2500 ms | Silence after last digit = number complete |
|
||||
Reference in New Issue
Block a user