My take on a @DrZzs Motorised Automated Crank Window Opener

For version 2.0 I ditched the cam (Not high enough resolution for my use case) and learnt to 3d design/3d print.

Now ‘Cranky’ looks pretty good I reckon.

Edit: 2023-05-31.

Long Term Reliability: Still going strong!

Parts Lists:

  • D1 mini or similar (I’d probably go for an ESP32 these days)
  • L298N (for version 2 I went with a L298N mini rather than a full sized L298N, and powered the whole thing via 5v usb rather than a 12V wall wart). This makes it slower but simpler and more compact.
  • A bh1750. Consider getting one with a nice dome for athletics. Mines just poking through a hole in the top right there.
  • End Stop Limit Switch. Consider getting a slightly larger one and think about how/where you’ll mount this.
  • Momentary button to toggle state. Mine is mounted on the far side that you can’t see in this photo. See config. If open, then close, if closed then open, if moving then stop, if stopped move in opposite direction to last.
  • A suitable coupler.
  • A motor (I’m driving my 12V motor with 5V, It takes about 3min to open!)
  • You could think about adding a rain drop sensor. Or building one separately. Close the windows when it rains!

Config:

Expand Me
substitutions:
  devicename: shed_window_crank
  friendly_name: Shed Cranky
  device_description: Shed Cranky

esphome:
  name: $devicename
  comment: ${device_description}
  platform: ESP8266
  board: d1_mini

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

# Enable logging
logger:
  # level: VERY_VERBOSE
# Enable Home Assistant API
api:

ota:

# deep_sleep:
  # run_duration: 24h
  # sleep_duration: 1s

text_sensor:
# Reports the ESPHome Version with compile date
  - platform: version
    name: ${friendly_name} ESPHome Version
    #Tracks last movement direction to help with the one-touch sit/stand toggle button.

# ##########################################################################################
# # Light Sensor - Needs i2c and the data/clock pins
# ##########################################################################################
i2c:
  sda: 4
  #D1 Data D2/GPIO4 > Green >  BH1750 SDA
  scl: 5
  #D1 Clock D1/GPIO5 > blue >  BH1750 SCL
  scan: True 
  id: bus_b
sensor:
  - platform: bh1750
    name: "Illuminance Shed Window"
    address: 0x23
    update_interval: 60s
    filters:
      - median:
          window_size: 3
          send_every: 3
   
##########################################################################################
# Motor Control
##########################################################################################
#Set up control, Define Pins
#GPIO15 = D8 >>> IN3
#GPIO13 = D7 >>> IN4
output:
  - platform: gpio
    id: 'win_close_shed'
    pin: D8
  - platform: gpio
    id: 'win_open'
    pin: D7
  
#USe the pins above in two switches.
switch:
  - platform: output
    name: "winclose_shed"
    output: 'win_close_shed'
    id: winclose_shed
    internal: false
  - platform: output
    name: "winopen_shed"
    output: 'win_open'
    id: winopen_shed
    internal: false

#Use the switches to define a cover.
cover:
  - platform: template
    name: "Shed Window"
    id: tr_win_open_shed
    # optimistic: true
    device_class: window
    lambda: |-
      if (id(shed_win_state).state) {
        return COVER_CLOSED;
      } else {
        return COVER_OPEN;
      }
    # 
      # if (id(shed_win_state).state) {
        # return COVER_CLOSED;
      # } else {
        # return COVER_OPEN;
      # }
    open_action:
        #Don't open if open
      then:
        if:
          condition:
            binary_sensor.is_on: shed_win_state
          then:
            - switch.turn_off: winclose_shed
            - switch.turn_on: winopen_shed 
            - delay: 165s
            - switch.turn_off: winopen_shed
          else:
    close_action:
        #Don't close if closed
      then:
        if:
          condition:
            binary_sensor.is_off: shed_win_state
          then:
            - switch.turn_off: winopen_shed
            - switch.turn_on: winclose_shed
            - delay: 170s
            - switch.turn_off: winclose_shed
          else:
#for stop button
    stop_action:
      - switch.turn_off: winclose_shed
      - switch.turn_off: winopen_shed


##########################################################################################
# End Stop
##########################################################################################
binary_sensor:
  - platform: status
    name: "Shed Window ESP32 Status"
#D5 > yellow > C
#Ground > black > NO
  - platform: gpio
    # device_class: window
    internal: false
    pin:
      number: D6
      #try activating pullup...
      mode: INPUT_PULLUP
    #D3 problematic. Try D5
    name: "shed window end stop"
    id: "shed_win_state"
    on_press:
      then:
        - switch.turn_off: winclose_shed
        - switch.turn_off: winopen_shed
    filters:
      - invert:
# ##########################################################################################
# # Button Placeholder
# ##########################################################################################      

# // window is opening
# // window is open and not moving   
  # // window is closing    
  # // win is closed and not moving                  
  - platform: gpio
#D4 (yellow) to whatever
    pin: D4
    name: "toggle shed window"
    id: "toggle_shed_window"
    internal: true
    filters: 
      invert: 
    on_press: 
      then: 
        - lambda: | 
            if (id(tr_win_open_shed).position == COVER_OPEN) {
              if (id(winopen_shed).state){
                id(tr_win_open_shed).stop();
              } else { 
                id(tr_win_open_shed).close();
              } 
            } else { 
                if (id(winclose_shed).state){
                  id(tr_win_open_shed).stop();
                } else {
                id(tr_win_open_shed).open(); 
                }
            }
        # - lambda: | 
        #     if (id(tr_win_open_shed).current_operation == CoverOperation::COVER_OPERATION_IDLE) {
        #       // Cover is not opening or closing, toggle it. https://esphome.io/components/cover/index.html#cover-stop-action
        #       auto call = id(tr_win_open_shed).make_call();
        #       call.set_command_toggle();
        #       call.perform();
        #     } else {
        #       // Cover is opening or closing, stop it.
        #       auto call = id(tr_win_open_shed).make_call();
        #       call.set_command_stop();
        #       call.perform();
        #     }


Enclosure:
https://www.printables.com/model/494747-cranky-window-opener-enclosure/files

Edit: 2023-10-28 added details to clarify features.

2 Likes