ESPHome automated shades a 2 for 1 deal

I finally figured it out. I had been trying to find an ESPhome project to copy for a while the would allow me to create my own automated shades. I wanted to use the cheap spring-loaded cut-to-fit shades you can buy for about $10 a piece. Without a complete step-by-step tutorial online, I figured why not piece together parts of other projects. So i did.
I took the basic physical design from this Instrctables post: https://www.instructables.com/DIY-Motorized-WiFi-Roller-Blind-ESP8266-Blynk/ . The ESPhome code I used and modified was from:
DIY Motorised Smart Blinds .
Each of these projects used a D1 mini to control one window covering. Blinds in the case of everythingsmarthome and shades in the instructables post but I wanted to controlled two windows, two shades with one D1. So I did, and I gave them manual controls. I also made it battery powered and give it a LUX sensor to detect the level of light outside. The batteries are 18650s and I’m charging them with a solar panel suction-cupped to the window.
Don’t get me wrong it has its issues. The batteries only last three days, so I ordered a 30 watt solar panel to take the place of my 1.5 watt panel. Hopefully that will help when it eventually gets here.
I’m using almost every pin of this D1. If anyone wants my ESPhome code or more information let me know. I’m even toying with the idea of creating my own custom PCB for the project.

Edit ESPhome code below:

esphome:
  name: living-room-shades

esp8266:
  board: d1_mini

# Enable logging
logger:

# Enable Home Assistant API
api:
  encryption:
    key: 

ota:
  password: 

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

  # Enable fallback hotspot (captive portal) in case wifi connection fails
  ap:
    ssid: 
    password: 

captive_portal:
    
cover:
  - platform: template
    name: "My Blind 0"
    id: my_blind0
    device_class: blind
    open_action:
      - stepper.set_target:
          id: my_stepper0
          target: 60000
      - sensor.template.publish:
          id: position0
          state: !lambda return id(my_stepper0).target_position;
    close_action:
      - stepper.set_target:
          id: my_stepper0
          target: 0
      - sensor.template.publish:
            id: position0
            state: !lambda return id(my_stepper0).target_position;
    stop_action:
      - stepper.set_target:
          id: my_stepper0
          target: !lambda return id(my_stepper0).current_position;
      - sensor.template.publish:
            id: position0
            state: !lambda return id(my_stepper0).current_position;
    optimistic: true
    assumed_state: true

  - platform: template
    name: "My Blind 1"
    id: my_blind1
    device_class: blind
    open_action:
      - stepper.set_target:
          id: my_stepper1
          target: -60000
      - sensor.template.publish:
          id: position1
          state: !lambda return id(my_stepper1).target_position;
    close_action:
      - stepper.set_target:
          id: my_stepper1
          target: 0
      - sensor.template.publish:
            id: position1
            state: !lambda return id(my_stepper1).target_position;
    stop_action:
      - stepper.set_target:
          id: my_stepper1
          target: !lambda return id(my_stepper1).current_position;
      - sensor.template.publish:
            id: position1
            state: !lambda return id(my_stepper1).current_position;
    optimistic: true
    assumed_state: true

sensor:
  - platform: template
    name: "My Blind 0 Position"
    id: position0

  - platform: template
    name: "My Blind 1 Position"
    id: position1

  - platform: adc
    pin: VCC
    id: "VCC"
    internal: true
    
  - platform: template
    name: "battery_level"
    unit_of_measurement: '%'
    update_interval: 60s
    lambda: |-
      return ((id(VCC).state /3.30) * 100.00); 

  - platform: adc
    pin: A0
    name: "LUX Sensor"
    update_interval: 60s
    unit_of_measurement: lux
    filters:
      - lambda: |-
          return (x / 10000.0) * 2000000.0;

binary_sensor:
  - platform: gpio
    pin: TX
    id: "Open_Button"
    on_press:
      then:
        - stepper.set_target:
            id: my_stepper0
            target: !lambda return id(my_stepper0).current_position;
        - sensor.template.publish:
            id: position0
            state: !lambda return id(my_stepper0).current_position;
        - stepper.set_target:
            id: my_stepper1
            target: !lambda return id(my_stepper1).current_position;
        - sensor.template.publish:
            id: position1
            state: !lambda return id(my_stepper1).current_position;
    on_release:
      then:
        - stepper.set_target:
            id: my_stepper0
            target: 60000
        - sensor.template.publish:
            id: position0
            state: !lambda return id(my_stepper0).target_position;
        - stepper.set_target:
            id: my_stepper1
            target: -60000
        - sensor.template.publish:
            id: position1
            state: !lambda return id(my_stepper1).target_position;
    on_double_click:
      min_length: 50ms
      max_length: 350ms
      then:
        - stepper.set_target:
            id: my_stepper0
            target: 60000
        - sensor.template.publish:
            id: position0
            state: !lambda return id(my_stepper0).target_position;
        - stepper.set_target:
            id: my_stepper1
            target: -60000
        - sensor.template.publish:
            id: position1
            state: !lambda return id(my_stepper1).target_position;


  - platform: gpio
    pin: RX
    id: "Close_Button"
    on_press:
      then:
        - stepper.set_target:
            id: my_stepper0
            target: !lambda return id(my_stepper0).current_position;
        - sensor.template.publish:
            id: position0
            state: !lambda return id(my_stepper0).current_position;
        - stepper.set_target:
            id: my_stepper1
            target: !lambda return id(my_stepper1).current_position;
        - sensor.template.publish:
            id: position1
            state: !lambda return id(my_stepper1).current_position;
    on_release:
      then:
        - stepper.set_target:
            id: my_stepper0
            target: 0
        - sensor.template.publish:
            id: position0
            state: !lambda return id(my_stepper0).target_position;
        - stepper.set_target:
            id: my_stepper1
            target: 0
        - sensor.template.publish:
            id: position1
            state: !lambda return id(my_stepper1).target_position;
    on_double_click:
      min_length: 50ms
      max_length: 350ms
      then:
        - stepper.set_target:
            id: my_stepper0
            target: 0
        - sensor.template.publish:
            id: position0
            state: !lambda return id(my_stepper0).target_position;
        - stepper.set_target:
            id: my_stepper1
            target: 0
        - sensor.template.publish:
            id: position1
            state: !lambda return id(my_stepper1).target_position;
    

stepper:
  - platform: uln2003
    id: my_stepper0
    pin_a: D1
    pin_b: D2
    pin_c: D3
    pin_d: D4
    max_speed: 725 steps/s
    sleep_when_done: True
    acceleration: inf
    deceleration: inf

  - platform: uln2003
    id: my_stepper1
    pin_a: D5
    pin_b: D6
    pin_c: D7
    pin_d: TX
    max_speed: 725 steps/s
    sleep_when_done: True
    acceleration: inf
    deceleration: inf
3 Likes

That’s kind of the point of this forum category.

1 Like

I like your idea but I would prefer ESPHome instead
thanks for sharing!

I’ve edited the post with the ESPhome yaml.

2 Likes