Tag: ESPHome

Automatische Jaloezie Aansturing

Automatische Jaloezie Aansturing

DIY Automatische Jaloezie Aansturing met ESP32, Steppermotor en 3D‑Geprinte Behuizing

Wil je je houten jaloezieën automatiseren zonder dure commerciële systemen?
In dit project bouwen we een volledig lokaal werkende jaloezie‑controller met:

  • een ESP32
  • een 28BYJ‑48 steppermotor
  • een ULN2003 driver
  • micro‑switches
  • een 3D‑geprinte behuizing
  • ESPHome + Home Assistant

Hieronder vind je alle onderdelen, de montage, foto’s van het project, schema’s en de volledige ESPHome‑YAML.


Benodigde onderdelen

Mechanisch

Elektronica


Fotoreportage van het project

Foto 1 – Tandwielmechanisme
Close‑up van het interne tandwiel van het jaloeziemechanisme. Dit is het deel waar de motor op aangrijpt.

Foto 2 – Steppermotor + tandwieloverbrenging
De 28BYJ‑48 motor gekoppeld aan het grote tandwiel van de jaloezie.

Foto 3 – Motor in montageframe
De motor zit stevig geklemd in de 3D‑geprinte houder.

Foto 4 – ULN2003 driverboard
Het driverboard dat de steppermotor aanstuurt.

Foto 5 – ESP32 module
De compacte ESP32 D1 mini die in de behuizing past.

Foto 6 – ESP32 bedrading
De bedrading naar de ULN2003 driver.

Foto 7 – Eindschakelaars
De micro‑switches voor handmatige bediening.

Foto 8 – Complete montage
Alle onderdelen gemonteerd in de 3D‑geprinte behuizing.


Elektrisch schema

[ESP32 D1 Mini]
 ├─ 5V  ───────────────→  [ULN2003] VCC
 ├─ GND ───────────────→  [ULN2003] GND
 ├─ GPIO22 ────────────→  [ULN2003] IN1
 ├─ GPIO21 ────────────→  [ULN2003] IN2
 ├─ GPIO17 ────────────→  [ULN2003] IN3
 └─ GPIO16 ────────────→  [ULN2003] IN4

[ULN2003]
 └─ Motor connector → 28BYJ‑48 Steppermotor

[ESP32 D1 Mini]
 ├─ GPIO26 ───────────→  Micro‑switch CW (NO)
 └─ GPIO18 ───────────→  Micro‑switch CCW (NO)

Micro‑switches:
 ├─ COM → GND
 └─ NO  → GPIO (26 of 18)

Mechanisch schema

[3D-geprinte behuizing]
 ├─ Kamer 1: Steppermotor (28BYJ‑48)
 │     └─ Motoras grijpt in het tandwiel van het jaloeziemechanisme
 │
 ├─ Kamer 2: ULN2003 driverboard
 │     └─ Motorstekker direct aangesloten
 │
 ├─ Kamer 3: ESP32 D1 Mini
 │     └─ JST-connector naar driverboard
 │
 └─ Zijkant: Micro-switch CW & CCW
       ├─ Roller raakt de handmatige bedieningshendel
       └─ Functie: handmatige bediening (links/rechts)

Overzichtsschema

[ESP32 D1 Mini]
        │
        ▼
[ULN2003 Driverboard]
        │
        ▼
[28BYJ‑48 Steppermotor]
        │
        ▼
[Jaloezie tandwielmechanisme]

Handmatige bediening:
[Micro-switch CW] ←─┐
[Micro-switch CCW] ←┘

Montage – stap voor stap

1. Print de behuizing

Alle onderdelen passen met support printen. PLA of PETG werkt prima.

2. Monteer de steppermotor

Schuif de motor in de houder en zorg dat het tandwiel goed grijpt.

3. Plaats de ULN2003 driver

Klik het board in de sleuf en verbind de motorstekker.

4. Monteer de ESP32

Verbind IN1–IN4 met de driver en sluit 5V + GND aan.

5. Monteer de micro‑switches

Deze worden gebruikt voor handmatige CW/CCW bediening.

6. Sluit alles aan

ESP32 → ULN2003 → motor → micro‑switches.

7. Upload de ESPHome firmware

Gebruik de YAML hieronder.

8. Automatische kalibratie

Bij elke reboot:

  • motor draait naar open‑positie
  • positie wordt op 0 gezet
  • motor draait naar half‑positie
  • positie wordt opnieuw op 0 gezet

ESPHome YAML (algemene versie)

# ============================================================
# JALOEZIE 
# Inclusief:
# - Absolute kalibratie bij opstart
# - 10s stabilisatietijd
# - Half-target instelbaar in Home Assistant (persistent)
# - Realtime positie & percentage
# - Software eindstops
# - Handmatige bediening (vasthouden = draaien)
# - Versie 20260220.1
# ============================================================
substitutions:
  name: stepper_blind
  blindname: "blind"
  friendly_name: "jaloezie"
  stepperid: ${name}

  calib_open_target: "36000"
  calib_half_target: "-18000"

  min_position: "-14000"
  max_position: "14000"

esphome:
  name: ${name}
  friendly_name: "${friendly_name}"

  on_boot:
    priority: -10
    then:
      - delay: 10s

      - lambda: |-
          if (id(calib_half_target_global) == 0) {
            id(calib_half_target_global) = ${calib_half_target};
          }

      - stepper.set_target:
          id: $stepperid
          target: ${calib_open_target}

      - wait_until:
          condition:
            lambda: 'return id($stepperid).current_position == ${calib_open_target};'

      - stepper.report_position:
          id: $stepperid
          position: 0
      - stepper.set_target:
          id: $stepperid
          target: 0

      - stepper.set_target:
          id: $stepperid
          target: !lambda return id(calib_half_target_global);

      - wait_until:
          condition:
            lambda: 'return id($stepperid).current_position == id(calib_half_target_global);'

      - stepper.report_position:
          id: $stepperid
          position: 0
      - stepper.set_target:
          id: $stepperid
          target: 0

esp32:
  board: esp32dev
  framework:
    type: esp-idf

globals:
  - id: calib_half_target_global
    type: int
    restore_value: true

stepper:
  - platform: uln2003
    id: $stepperid
    pin_a: GPIO22
    pin_b: GPIO21
    pin_c: GPIO17
    pin_d: GPIO16
    max_speed: 500 steps/s
    sleep_when_done: true


cover:
  - platform: template
    name: $blindname
    id: ${blindname}
    has_position: true
    device_class: blind

    open_action:
      - stepper.set_target:
          id: $stepperid
          target: ${max_position}

    close_action:
      - stepper.set_target:
          id: $stepperid
          target: ${min_position}

    stop_action:
      - stepper.set_target:
          id: $stepperid
          target: !lambda return id($stepperid).current_position;

    # SET POSITION action verkeerd om
#    position_action:
#      - lambda: |-
#          float target = (1.0 - pos) * (float(${max_position}) - float(${min_position})) + float(${min_position});
#          id($stepperid).set_target((int)target);

    position_action:
      - lambda: |-
          // percentage van HA → stepper positie (nu omgedraaid)
          float target = pos * (float(${max_position}) - float(${min_position})) + float(${min_position});
          id($stepperid).set_target((int)target);


    # Cover slider in HA → 0–1.0
    lambda: |-
      float percent = id(position_percent).state;
      return percent / 100.0;


sensor:
  - platform: template
    name: "$blindname Position"
    id: position
    accuracy_decimals: 0
    update_interval: 200ms
    lambda: |-
      return (int) id($stepperid).current_position;
    filters:
      - delta: 10

  - platform: template
    name: "$blindname Percentage"
    id: position_percent
    unit_of_measurement: "%"
    accuracy_decimals: 0
    update_interval: 200ms
    lambda: |-
      float pos = id($stepperid).current_position;
      return (int)((1.0 - ((pos - ${min_position}) / (float(${max_position}) - float(${min_position}))))) * 100.0;
    filters:
      - delta: 1.0

number:
  - platform: template
    name: "${blindname} Calib Half Target"
    id: calib_half_target_number
    min_value: -50000
    max_value: 50000
    step: 100
    restore_value: true
    on_value:
      then:
        - lambda: |-
            id(calib_half_target_global) = (int)x;

wifi:
  ssid: !secret wifi_ssid
  password: !secret wifi_password

logger:
ota:
api:

Conclusie

Met deze 3D‑geprinte behuizing, goedkope componenten en ESPHome heb je een
professionele jaloezie‑automatisering die volledig lokaal werkt en perfect integreert met Home Assistant.

Is er iets niet duidelijk, laat het gerust weten.

Loading

AB8SS integreren met Home Assistant via ESPHome: een complete gids

AB8SS integreren met Home Assistant via ESPHome: een complete gids

Veel gebruikers van de AB8SS audio‑switch lopen vroeg of laat tegen hetzelfde probleem aan: het apparaat werkt betrouwbaar, maar de seriële aansturing is… eigenzinnig. Het protocol verwacht exacte byte‑reeksen, echo’s, en reageert alleen correct als je de juiste state‑machine gebruikt. Standaard integraties werken daarom vaak niet of slechts half.

In deze blog laat ik zien hoe je de AB8SS volledig en stabiel kunt integreren met Home Assistant via ESPHome, inclusief een robuuste YAML‑configuratie die alle protocol‑eigenaardigheden netjes afhandelt.

Deze oplossing is ontwikkeld, getest en verfijnd met echte hardware — en werkt 100% betrouwbaar.

Waarom de AB8SS lastig is om aan te sturen

De AB8SS gebruikt een seriële interface met een aantal bijzonderheden:

  • Elke opdracht moet exact worden opgebouwd uit 4 bytes
  • Het apparaat stuurt een echo terug dat byte‑voor‑byte moet worden gevalideerd
  • Pas daarna volgt een status‑antwoord
  • Het apparaat accepteert geen nieuwe opdrachten zolang de vorige niet volledig is afgerond
  • Foutafhandeling is noodzakelijk om vastlopers te voorkomen

Veel implementaties falen omdat ze deze stappen niet strikt volgen.

Daarom hebben we een state‑machine gebouwd die:

  • elke byte valideert
  • timeouts afhandelt
  • commando’s in een wachtrij zet
  • de AB8SS nooit overspoelt
  • altijd in sync blijft met het apparaat

De oplossing: een robuuste ESPHome‑configuratie

De YAML‑configuratie die we hebben ontwikkeld bevat:

  • Een UART‑configuratie met correcte baudrate en framing
  • Een state‑machine die echo’s en antwoorden valideert
  • Een command‑queue zodat Home Assistant meerdere opdrachten kan sturen
  • Sensors die de actuele status van alle zones en bronnen teruggeven
  • Switches en selects om zones en inputs te bedienen
  • Volledige foutafhandeling en automatische recovery

Deze configuratie maakt de AB8SS net zo betrouwbaar als een native Home Assistant‑integratie.

Hoe het werkt (conceptueel)

  1. Home Assistant stuurt een opdracht (bijv. “Zone 3 → Input 2”).
  2. ESPHome zet het commando in een wachtrij.
  3. De state‑machine stuurt de 4 bytes naar de AB8SS.
  4. De AB8SS stuurt een echo terug → ESPHome valideert elke byte.
  5. Daarna stuurt de AB8SS een statusbericht.
  6. De state‑machine verwerkt het antwoord en werkt de entiteiten bij.
  7. Pas daarna wordt het volgende commando verstuurd.

Dit voorkomt dat de AB8SS “out of sync” raakt — een veelvoorkomend probleem.

De YAML‑configuratie

Klik deze link om de yaml file te downloaden

Hoe de state‑machine werkt

De kern van de oplossing is een compacte maar krachtige state‑machine die:

1. Een commando uit de queue haalt

Bijvoorbeeld: 050001FA* → Zone 1 aan

2. Een ATTENTION‑byte (!) stuurt

De AB8SS antwoordt met ! als hij klaar is.

3. Elke byte van het commando stuurt

En wacht op de echo.

4. Echo valideert

Als de echo niet klopt → retry Na 5 mislukte pogingen → abort

5. Statusframe verwerkt

Bijvoorbeeld: 84xxxxxx* → bitmask van alle zones + input

6. Home Assistant‑entiteiten bijwerkt

Elke zone wordt direct geüpdatet.

7. Automatisch een statuspoll plant

Zodat Home Assistant altijd synchroon blijft.

Home Assistant entiteiten

De YAML maakt automatisch de volgende entiteiten aan:

Zones (switches)

  • Zone 1 t/m Zone 8 → aan/uit

Inputselectie (switch)

  • Input A/B

Debug‑modus

  • Logt alle RX/TX bytes in realtime

Waarom deze implementatie uniek is

Deze oplossing:

  • werkt met echte echo‑validatie
  • heeft retry‑logica
  • voorkomt dat de AB8SS “out of sync” raakt
  • gebruikt een command‑queue zodat Home Assistant meerdere opdrachten tegelijk kan sturen
  • verwerkt statusframes en houdt Home Assistant realtime up‑to‑date
  • bevat timeouts en foutafhandeling
  • is volledig ESPHome‑native (geen custom component nodig)

Dit is de meest complete en betrouwbare AB8SS‑integratie die momenteel beschikbaar is.

Installatie‑stappen

Flash een ESP32 met ESPHome

Sluit de AB8SS aan via UART op de ESP32
Ik gebruik hiervoor een RS232 naar TTL module, zoals bijvoorbeeld deze.
En een D1 Mini Live ESP32.

  • TX → RX
  • RX → TX
  • GND → GND

Upload de YAML

Voeg het apparaat toe aan Home Assistant

Bedien zones en inputs direct vanuit HA

Gebruik debug‑modus om communicatie te monitoren

Conclusie

De AB8SS is een fantastisch apparaat, maar het protocol vraagt om een zorgvuldige implementatie. Met deze ESPHome‑configuratie kun je de AB8SS volledig integreren in Home Assistant, zonder instabiliteit of half werk.

Deze oplossing is:

  • robuust
  • getest
  • onderhoudsvrij
  • volledig lokaal
  • makkelijk uit te breiden

State‑machine diagram voor de AB8SS‑implementatie

               ┌──────────────────────────┐
               │          IDLE            │
               │  - Geen actief commando  │
               │  - Queue check           │
               │  - Poll timer check      │
               └───────────┬──────────────┘
                           │
                           ▼
               ┌──────────────────────────┐
               │     ATTENTION_SEND       │
               │  TX: "!"                 │
               │  Deadline = now + 100ms  │
               └───────────┬──────────────┘
                           │
                           ▼
               ┌──────────────────────────┐
               │     ATTENTION_WAIT       │
               │  Wacht op RX: "!"        │
               │  Timeout → ABORT         │
               └───────────┬──────────────┘
                           │
                           ▼
               ┌──────────────────────────┐
               │        CMD_SEND          │
               │  TX: current_cmd[pos]    │
               │  Deadline = 5–10ms       │
               └───────────┬──────────────┘
                           │
                           ▼
               ┌──────────────────────────┐
               │        CMD_WAIT          │
               │  Wacht op echo           │
               │  Echo OK → pos++         │
               │  Echo NOK → "-" + ABORT  │
               └───────────┬──────────────┘
                           │
                           ▼
               ┌──────────────────────────┐
               │          DONE            │
               │  - Command klaar         │
               │  - Poll in queue         │
               │  - next_allowed = +50ms  │
               └───────────┬──────────────┘
                           │
                           ▼
               ┌──────────────────────────┐
               │          ABORT           │
               │  - Retry tot 5x          │
               │  - Daarna drop           │
               │  - next_allowed = +300ms │
               └──────────────────────────┘

Behuizing

De ESP32 en uart zijn eventueel in een 3D geprinte behuizing te plaatsen

Loading