My take on a @DrZzs Motorised Automated Crank Window Opener

My take on a @DrZzs Motorised Automated Crank Window Opener (https://www.youtube.com/watch?v=Kz8dQG2_uhw&t=2s)



Based on DrZzs project but with:

  • A much worse enclosure made from a junction box, a bracket and some Oogoo.
  • An Esp32 Cam (ESP32 Cam - working! - #356 by ekesa).
  • A lux sensor (bh1750 sensor) to help automate internal lighting based on ambient outside levels.
  • An end stop switch off Ali Express (rather than a reed - I got that idea from the Youtube comments)

For the enclosure, it was my first time expermenting with Oogoo (Which is DIY Sugru. Sugru is awesome stuff.)

I want to teach the camera to take pictures and notify me of hot air ballons that float by some mornings based on this and this:
OpenCV: Computer Vision / Image processing for Window Roller Blind State (Up/Down)
@robmarkcole general approach: Image Classification with Docker/Machinebox

I’ll also do some automations so that when temp goes above/below threshold, reverse cycle air con kicks in, and windows close.

esphome:
  name: esp32cam_1
  platform: ESP32
  board: esp32dev

wifi:
  ssid: "XXXXXXXXXXX"
  password: "YYYYYYYYYYYYYY"

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

ota:

# esp32_ble_tracker:
  # scan_interval: 20s

# ESP32-CAM
esp32_camera:
  name: esp33_cam1
  external_clock:
    pin: GPIO0
    frequency: 20MHz
  i2c_pins:
    sda: GPIO26
    scl: GPIO27
  data_pins: [GPIO5, GPIO18, GPIO19, GPIO21, GPIO36, GPIO39, GPIO34, GPIO35]
  vsync_pin: GPIO25
  href_pin: GPIO23
  pixel_clock_pin: GPIO22
  power_down_pin: GPIO32
  max_framerate: 5 fps
  
  
i2c:
  sda: GPIO2
  scl: GPIO14
  scan: True
  id: bus_a

sensor:
  - platform: bh1750
    name: "BH1750 Illuminance 2"
    address: 0x23
    update_interval: 30s
    filters:
      - median:
          window_size: 3
          send_every: 3
output:
  - platform: gpio
    id: 'win_cr1'
    pin: GPIO12
  - platform: gpio
    id: 'win_cr2'
    pin: GPIO13
  
switch:
  - platform: output
    name: "wincr1"
    output: 'win_cr1'
    id: wincr1
  - platform: output
    name: "wincr2"
    output: 'win_cr2'
    id: wincr2

cover:
  - platform: template
    name: "Shed Window"
    id: tr_win_open
    optimistic: true
    open_action:
      - switch.turn_off: wincr1
      - switch.turn_on: wincr2
      - delay: 55s
      - switch.turn_off: wincr2
    close_action:
      - switch.turn_off: wincr2
      - switch.turn_on: wincr1
      - delay: 60s
      - switch.turn_off: wincr1
#for stop button
    stop_action:
      - switch.turn_off: wincr1
      - switch.turn_off: wincr2

binary_sensor:
  - platform: gpio
    pin: GPIO15
    name: "shed window state"
    id: "shed_win_state"
    on_press:
      then:
        - switch.turn_off: wincr1
        - switch.turn_off: wincr2
    filters:
      - invert:
3 Likes

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

Great improvement, amazing what a bit of makeup does.

1 Like

Has a git been made for this? If not, I think I’m going to start from scratch with detailed instructions. I’m used to programming ESPs in C, this yaml thing is going to be new for me.

edit arg sorry I only noticed after this was a 4 year old thread :joy: didn’t mean to be a necromancer!

1 Like

No Git project.

I can add details on request (materials, config, 3d printed enclosure).

The logic is mostly taken from the DrZZZ project, and the enclosure design would likely be customised to your window.

They have been pretty solid and are still going. The main issues relate to how torque transfers through the design (force transfers between motor, through enclosure, to window frame).

Yeah I figured torque would be the issue. I’m going to go with a worm screw and a frame-wide bracket I think to take the torque and spread it on the entire base of the window frame.

I would certainly appreciate the details of yours, I’ll be documenting my build too and will share everything I have! I’ll certainly make a GIT though so that at least the software part can be shared, even if people have to make their own variants of the hardware. If you’re okay with it, I’d love to include your build steps as an example of alternative builds. I figure once we have a handful up there, someone will take the best of all of our ideas and make a solid design.

1 Like

I’ve added more details to this post. Let me know if you need more. Feel free to remix as you wish.

Citing my project is no problem and appreciated but also don’t worry about it too much if you don’t.

1 Like

Curious - did you try running the L298N mini at 12V? I know its only rated at 10V, just not sure if 12V will fry it…

I don’t know. I just power it via the esp 5v pin.

This is my take on a parameterized version of the crank window opener… Parametric Window Crank by ibycus - Thingiverse

1 Like

Nice one. Thanks for sharing.

Mine are still going strong 3+ years later (admittedly with the occasional rectifiable mechanical failure which relates to the case popping open due to the internal load path / strain through the enclosure)

G’day @Mahko_Mahko , thanks for putting this together! My window frame looks similar so I’ve printed your enclosure, just wondering how you screwed the coupler screws in? There’s no clearance in the enclosure to reach the screws once the motor has been placed in.

Also, wondering what the other 2 holes are for? I assume for switch buttons, and the little slot thing? Cheers!

Hey!

I’ve added some clarifications/additions to my main post. The holes are button and light sensor holes.

You may need to tweak my design a bit. Especially to keep the motor box holder bit really tight.

Yes screwing in the coupler screws is very tight access. For me I can just access the screws with the allen key if I have it rotated to a specific angle.

First do the window side of the coupler, then line up the motor and other side of the coupler so the screws points roughly to 2 o’clock and sneak your Allen key in there.

If you get stuck let me know and I’ll take a flick.

If you have any issues with the config let me know. I may have made minor updates to breaking changes etc.

Edit:
Oh and I forgot there are also holes for the usb cable and wires to the endstop.

Edit 2: Actually looking at my design, I forgot there are more.