> ## Documentation Index
> Fetch the complete documentation index at: https://docs.glifo.cat/llms.txt
> Use this file to discover all available pages before exploring further.

# ESPHome configuration

> Package system, component reference, and customization guide for the ED1 ESPHome integration.

Detailed explanation of the ESPHome configuration for the ED1 board.

## File structure

<Tree>
  <Tree.Folder name="ed1-hoas" defaultOpen>
    <Tree.File name="ed1-message.sample.yaml" />

    <Tree.File name="ed1-mqtt.sample.yaml" />

    <Tree.File name="ed1-status.sample.yaml" />

    <Tree.File name="secrets.yaml" />

    <Tree.File name="secrets.sample.yaml" />

    <Tree.Folder name="packages" defaultOpen>
      <Tree.File name="core.yaml" />

      <Tree.File name="hardware.yaml" />

      <Tree.File name="display.yaml" />

      <Tree.File name="fonts.yaml" />

      <Tree.File name="buzzer.yaml" />

      <Tree.File name="buttons.yaml" />

      <Tree.File name="sensors.yaml" />

      <Tree.File name="bluetooth.yaml" />

      <Tree.File name="ir-receiver.yaml" />

      <Tree.File name="led-matrix.yaml" />

      <Tree.File name="mqtt.yaml" />

      <Tree.File name="stepper.yaml" />
    </Tree.Folder>

    <Tree.Folder name="fonts">
      <Tree.Folder name="pixelmix">
        <Tree.File name="pixelmix.ttf" />
      </Tree.Folder>
    </Tree.Folder>
  </Tree.Folder>
</Tree>

## Modular package system

This project uses ESPHome's package system for modularity. Each sample config uses `!include` to import reusable components from the `packages/` directory.

### Basic structure

```yaml theme={null}
substitutions:
  device_name: ed1-mydevice
  friendly_name: ED1 My Device
  ap_ssid: ED1-MyDevice-Rescue

packages:
  core: !include packages/core.yaml
  hardware: !include packages/hardware.yaml
  display: !include packages/display.yaml
  fonts: !include packages/fonts.yaml
  buzzer: !include packages/buzzer.yaml
  buttons: !include packages/buttons.yaml
  sensors: !include packages/sensors.yaml
  bluetooth: !include packages/bluetooth.yaml
```

### Extending package components

Use `!extend` to override or add to components defined in packages:

```yaml theme={null}
# Override display lambda
display:
  - id: !extend internal_display
    lambda: |-
      // Custom display code here

# Add custom button behavior
binary_sensor:
  - id: !extend btn_ok
    on_press:
      - logger.log: "Custom OK action"
      - rtttl.play: 'success:d=8,o=5,b=160:c,e,g'
```

### Creating a new configuration

1. Copy an existing sample (e.g., `ed1-message.sample.yaml`)
2. Update the `substitutions` section with your device name
3. Add or remove packages as needed
4. Override display lambda and button behaviors for your use case

## Secrets setup

1. Copy the sample file:
   ```bash theme={null}
   cp secrets.sample.yaml secrets.yaml
   ```

2. Edit `secrets.yaml` with your values:
   ```yaml theme={null}
   wifi_ssid: "YourNetworkName"
   wifi_password: "YourWiFiPassword"
   api_encryption_key: "base64-encoded-key"
   ota_password: "secure-ota-password"
   fallback_ap_password: "fallback-password"
   ```

3. Generate an API key:
   ```bash theme={null}
   openssl rand -base64 32
   ```

## Package reference

The following sections describe what each package contains. These are automatically included when you use `!include packages/<name>.yaml`.

### Core configuration (packages/core.yaml)

```yaml theme={null}
esphome:
  name: ed1-rev23-a
  friendly_name: ED1 Rev 2.3 A

esp32:
  board: esp32dev
  framework:
    type: arduino
```

* **name**: Device hostname (lowercase, hyphens only)
* **friendly\_name**: Display name in Home Assistant
* **board**: Generic ESP32 dev board
* **framework**: Arduino for best compatibility

### Connectivity (packages/core.yaml)

```yaml theme={null}
wifi:
  ssid: !secret wifi_ssid
  password: !secret wifi_password
  ap:
    ssid: "ED1-Rev23-Rescue"
    password: !secret fallback_ap_password

captive_portal:
```

* **ap**: Fallback access point if WiFi fails
* **captive\_portal**: Web config when in AP mode

### Hardware buses (packages/hardware.yaml)

```yaml theme={null}
spi:
  clk_pin: GPIO18
  mosi_pin: GPIO23
  miso_pin: GPIO19

i2c:
  sda: GPIO21
  scl: GPIO22
  scan: true
  id: bus_i2c
```

* **scan: true**: Logs detected I2C devices on boot

### Fonts (packages/fonts.yaml)

```yaml theme={null}
font:
  - file: "fonts/pixelmix/pixelmix.ttf"
    id: pixel_font
    size: 8
  - file: "fonts/pixelmix/pixelmix.ttf"
    id: large_font
    size: 16
```

The font file is included in the `fonts/` directory.

### TFT display (packages/display.yaml)

```yaml theme={null}
display:
  - platform: st7735
    id: internal_display
    cs_pin: GPIO5
    dc_pin: GPIO9
    reset_pin: GPIO10
    rotation: 0
    model: "INITR_GREENTAB"
    col_start: 2
    row_start: 3
    device_width: 128
    device_height: 128
    update_interval: 1s
    lambda: |-
      // Drawing code here
```

**Display layout:**

| Line | Content         | Color  |
| ---- | --------------- | ------ |
| 1    | "ED1 FULL"      | Green  |
| 2    | IP address      | White  |
| 3    | CPU temperature | White  |
| 4    | Matrix text     | Yellow |

**Model Options:**

* `INITR_GREENTAB`: Use with `row_start: 3` for 1.44" 128x128 displays (equivalent to Adafruit's INITR\_144GREENTAB)
* `INITR_BLACKTAB`: Alternative initialization
* `INITR_18REDTAB`: For 1.8" displays

### LED matrix display (packages/led-matrix.yaml)

```yaml theme={null}
display:
  - platform: addressable_light
    id: led_matrix_display
    addressable_light_id: led_matrix_light
    width: 32
    height: 8
    pixel_mapper: |-
      if (x % 2 == 0) return (x * 8) + y;
      return (x * 8) + (7 - y);
    update_interval: 50ms
    lambda: |-
      // Text rendering
```

**pixel\_mapper**: Handles the serpentine wiring pattern where odd columns are reversed.

### LED matrix light (packages/led-matrix.yaml)

```yaml theme={null}
light:
  - platform: esp32_rmt_led_strip
    rgb_order: GRB
    chipset: WS2812
    pin: GPIO12
    num_leds: 256
    name: "ED1 LED Matrix"
    id: led_matrix_light
    default_transition_length: 0s
    color_correct: [40%, 40%, 40%]
```

* **platform: esp32\_rmt\_led\_strip**: ESPHome native driver using ESP-IDF 5.x RMT
* **rgb\_order: GRB**: Color order (Green-Red-Blue)
* **chipset: WS2812**: LED chipset type
* **color\_correct**: Reduces brightness to 40% (power savings)

> **Note**: We use `esp32_rmt_led_strip` instead of `neopixelbus` for compatibility with the IR receiver. Both use the RMT peripheral but the native driver uses the newer ESP-IDF 5.x API.

### Bluetooth proxy (packages/bluetooth.yaml)

```yaml theme={null}
esp32_ble_tracker:
  scan_parameters:
    interval: 1100ms
    window: 1100ms

bluetooth_proxy:
  active: true
```

Extends Home Assistant's Bluetooth range. The ED1 acts as a BLE relay.

### MQTT (packages/mqtt.yaml)

Optional package for MQTT broker connectivity. Can be used alongside or instead of the native API.

```yaml theme={null}
mqtt:
  broker: !secret mqtt_broker
  username: !secret mqtt_user
  password: !secret mqtt_password
  topic_prefix: ed1/${device_name}
```

**Topics:**

* `ed1/<device_name>/message` - Subscribe to receive messages
* `ed1/<device_name>/status` - Publishes `online`/`offline`

**Usage:**

1. Add MQTT credentials to `secrets.yaml`
2. Include the package: `mqtt: !include packages/mqtt.yaml`
3. Send messages via CLI: `mosquitto_pub -t ed1/ed1-message/message -m "Hello!"`

**Choosing API vs MQTT:**

* Use **native API** for Home Assistant integration (auto-discovery, encryption)
* Use **MQTT** for multi-system integration (Node-RED, scripts, other devices)
* Both can be used simultaneously

### Stepper motors (packages/stepper.yaml)

Controls two 28BYJ-48 stepper motors via the MCP23009 I2C GPIO expander and ULN2004A Darlington drivers.

```yaml theme={null}
packages:
  stepper: !include packages/stepper.yaml
```

**Technical Details:**

* Uses direct I2C register writes (not ESPHome's mcp23008 component)
* Full-step mode: 512 steps = 1 complete revolution
* Non-blocking interval-based stepping (2ms per step)
* Compatible with MicroBlocks "ED1 Stepper Motor" library

**Exposed Entities:**

| Entity                    | Type   | Description                 |
| ------------------------- | ------ | --------------------------- |
| `number.motor1_steps`     | Number | M1 steps (-4096 to +4096)   |
| `number.motor2_steps`     | Number | M2 steps (-4096 to +4096)   |
| `button.motor1_cw`        | Button | M1 clockwise (512 steps)    |
| `button.motor1_ccw`       | Button | M1 counter-clockwise        |
| `button.motor2_cw`        | Button | M2 clockwise (512 steps)    |
| `button.motor2_ccw`       | Button | M2 counter-clockwise        |
| `button.motors_stop`      | Button | Stop all motors, power down |
| `button.motor_diagnostic` | Button | Log MCP23009 registers      |

**Usage Example:**

```yaml theme={null}
# In your main config, extend button behavior
binary_sensor:
  - id: !extend btn_up
    on_press:
      - script.execute:
          id: motor1_run
          steps: 128  # 1/4 turn forward
```

**Step Counts:**

* 128 steps = 1/4 turn (90°)
* 256 steps = 1/2 turn (180°)
* 512 steps = 1 full turn (360°)

### Buzzer (packages/buzzer.yaml)

```yaml theme={null}
output:
  - platform: ledc
    pin: GPIO26
    id: buzzer_output

switch:
  - platform: output
    name: "ED1 Buzzer"
    id: buzzer_switch
    output: buzzer_output
```

The buzzer uses PWM via the LEDC (LED Control) peripheral. Turning the switch on activates the buzzer with a continuous tone.

### IR receiver (packages/ir-receiver.yaml)

```yaml theme={null}
remote_receiver:
  pin:
    number: GPIO35
    inverted: true
  dump: all
  on_nec:
    then:
      - lambda: |-
          ESP_LOGI("IR", "NEC: address=0x%04X, command=0x%04X", x.address, x.command);
  on_samsung:
    then:
      - lambda: |-
          ESP_LOGI("IR", "Samsung: data=0x%08X", x.data);
```

* **dump: all**: Logs all received IR codes (useful for debugging)
* **on\_nec/on\_samsung**: Protocol-specific handlers
* IR codes appear in ESPHome logs, not as Home Assistant entities
* Use to trigger automations based on remote control buttons

### Touch buttons (packages/buttons.yaml)

```yaml theme={null}
esp32_touch:
  setup_mode: false

binary_sensor:
  - platform: esp32_touch
    id: btn_up
    name: "ED1 Button Up"
    pin: GPIO4
    threshold: 500
    on_press:
      - logger.log: "Button Up PRESSED"
```

**Threshold Tuning:**

* Default: 500
* If too sensitive: Increase threshold
* If not responding: Decrease threshold
* Enable `setup_mode: true` temporarily to see raw values

### Sensors (packages/sensors.yaml)

```yaml theme={null}
# Safe RSSI value for display use (handles NaN before first reading)
globals:
  - id: wifi_rssi
    type: int
    initial_value: '-100'

sensor:
  - platform: wifi_signal
    name: "ED1 WiFi Signal"
    id: wifi_signal_sensor
    update_interval: 10s
    on_value:
      - lambda: 'id(wifi_rssi) = (int)x;'

  - platform: internal_temperature
    name: "ED1 CPU Temperature"
    id: cpu_temp

  - platform: adc
    pin: GPIO34
    name: "ED1 Light Level"
    attenuation: 12db
    unit_of_measurement: "%"
    filters:
      - multiply: 30.3  # Scale to 0-100%
```

**Note**: The `wifi_rssi` global provides a safe integer value for display code. Before the first WiFi signal reading (\~10 seconds after boot), the sensor returns NaN which can cause display issues when cast to int. The global defaults to -100 dBm and updates on each reading.

### Text input (packages/led-matrix.yaml)

```yaml theme={null}
text:
  - platform: template
    name: "ED1 Matrix Text"
    id: matrix_text_input
    optimistic: true
    min_length: 0
    max_length: 20
    mode: text
```

Allows Home Assistant to send text to display on the LED matrix.

## Customization

### Change display content

Modify the `lambda` in the display section:

```yaml theme={null}
lambda: |-
  it.fill(Color(0, 0, 0));
  it.print(0, 0, id(pixel_font), Color(255, 0, 0), "Custom Text");
```

### Add button actions

```yaml theme={null}
binary_sensor:
  - platform: esp32_touch
    id: btn_ok
    name: "ED1 Button OK"
    pin: GPIO15
    threshold: 500
    on_press:
      - light.toggle: led_matrix_light
```

### Adjust matrix brightness

Change `color_correct` values (0-100%):

```yaml theme={null}
color_correct: [20%, 20%, 20%]  # Dimmer
color_correct: [100%, 100%, 100%]  # Full brightness
```

## Troubleshooting

### Device not detected via USB

The ED1 uses a CP2102N USB-to-UART chip. Install the driver:

* Download from [Silicon Labs CP210x Drivers](https://www.silabs.com/developers/usb-to-uart-bridge-vcp-drivers)
* Install for your OS (Windows, macOS, Linux)
* Reconnect the USB cable
* The device should appear as `/dev/ttyUSB0` (Linux), `/dev/cu.SLAB_USBtoUART` (macOS), or `COM3` (Windows)

### Display shows garbage

* Check `model` setting matches your display
* Try adjusting `col_start` and `row_start` offsets
* Verify SPI pins are correct

### Touch buttons not working

* Enable `setup_mode: true` in `esp32_touch`
* Check logs for raw touch values
* Adjust threshold based on idle vs touched values

### LED matrix wrong colors

* Change `rgb_order` from `GRB` to `RGB` or `BRG`
* Some strips use different color orders

### WiFi connection issues

* Check signal strength sensor
* Reduce `update_interval` on sensors to reduce traffic
* Try static IP configuration

### Device not discovered

* Ensure API encryption key matches
* Check Home Assistant logs for connection attempts
* Verify device is on same network subnet
