DIY Zigbee Roller & Venetian blinds automation

With 12 windows with blinds, I wanted to automate the opening & closing. This was my journey:

I am using zigbee2mqtt to control all of my zigbee devices. Zigbee2mqtt also supports various diy firmware developments.

Bill Of Materials:
Motor (venetian blinds 3RPM, rollerblinds 30 RPM): https://www.aliexpress.com/item/32828852765.html?spm=a2g0s.9042311.0.0.27424c4d4bFBng
Brass coupling (venetian blind): https://www.aliexpress.com/item/32880631736.html?spm=a2g0s.9042311.0.0.27424c4d6SIdVi
Flange (roller blind): https://www.aliexpress.com/item/32915216261.html?spm=a2g0s.9042311.0.0.27424c4dtk8IPt
Zigbee module: https://www.aliexpress.com/item/4000037073363.html?spm=a2g0s.9042311.0.0.27424c4dejBHRb
Motor driver L298N: https://www.aliexpress.com/item/32586557008.html?spm=a2g0s.9042311.0.0.27424c4d0lFz8H
3.3 Volt converter for CC2530 board: https://www.aliexpress.com/item/32973365190.html?spm=a2g0s.9042311.0.0.27424c4dulOALv

Mechanical construction:

Connections CC2530, L298N, DC Motor:
New-Dual-H-Bridge-DC-Stepper-Motor-Drive-Controller-Board-Module-L298N-for-Arduino.jpg_50x50

*CC2530 -> LN298N
P11-> IN1
P12-> IN2
P13-> IN3
P14-> IN4

*DC motor 1 : OUT 2
*DC motor 2 : OUT 3
*Connect 12v DC supply to LN298N
*Connect 3.3V from converter to CC2530
*Make sure CC2530 and L298N have the same ground connection

Prepare the CC2530 firmware:
I use the configurable firmware from: http://ptvo.info and made this configuration:
ptvo to create my own firmware.

Flash CC2530:
The custom firmware can be flashed with CC debugger:
ccdebugger_cc2530
and the free software from TI: SmartRF Flash programmer ( NOT V2 ).

Appearance in Hassio:
When the CC2530 module (my module is 0x00124b001d863d78) is joined into the zigbee network, the following entities will appear in Hassio:

switch.0x00124b001d863d78_switch_bottom_left
switch.0x00124b001d863d78_switch_bottom_right
switch.0x00124b001d863d78_switch_top_left
switch.0x00124b001d863d78_switch_top_right

and these switches are attached to

P11: switch.0x00124b001d863d78_switch_bottom_left
P12: switch.0x00124b001d863d78_switch_bottom_right
P13: switch.0x00124b001d863d78_switch_top_left
P14: switch.0x00124b001d863d78_switch_top_right

So:
DC motor 1 = P11:P12 = switch.XXXX_switch_bottom_left : switch.XXXX_switch_bottom_right
DC motor 2 = P13:P14 = switch.XXXX_switch_top_left : switch.XXXX_switch_top_right

Create Cover control in Hassio:
In this description I will just show the configuration of one CC2530/L298N/2 DC motors

First create two cover templates:

#########################################################
#                                                       #
#        ZIGBEE LUXAFLEX WEST                           #
#                                                       #
#########################################################

  - platform: template
    covers:
      lux_west_left:
        friendly_name: "Lux west left"
        open_cover:
          service: script.open_west_left
        close_cover:
          service: script.close_west_left
        stop_cover:
          service: switch.turn_off
          data:
            entity_id: 
              - switch.0x00124b001d863d78_switch_bottom_right
              - switch.0x00124b001d863d78_switch_bottom_left
          
  - platform: template
    covers:
      lux_west_right:
        friendly_name: "Lux west right"
        open_cover:
          service: script.open_west_right
        close_cover:
          service: script.close_west_right
        stop_cover:
          service: switch.turn_off
          data:
            entity_id: 
              - switch.0x00124b001d863d78_switch_top_right
              - switch.0x00124b001d863d78_switch_top_left      
       
#########################################################
#                                                       #
#            END OF CONFIGURATION FILE                  #
#                                                       #
#########################################################   

Create the scripts:
The milliseconds: 16000 delay is the time needed for the blinds to open or close. This is different for all the devices depending on the available current, type blind etc.

#########################################################
#                                                       #
#        ZIGBEE LUXAFLEX WEST                           #
#                                                       #
#########################################################

open_west_left:
  sequence:
    - service: switch.turn_on
      data:
        entity_id: switch.0x00124b001d863d78_switch_bottom_left
    - delay:
        milliseconds: 16000
    - service: switch.turn_off     
      data:
        entity_id: switch.0x00124b001d863d78_switch_bottom_left
      
close_west_left:
  sequence:
    - service: switch.turn_on
      data:
        entity_id: switch.0x00124b001d863d78_switch_bottom_right
    - delay:
        milliseconds: 16000
    -  service: switch.turn_off    
       data:
         entity_id: switch.0x00124b001d863d78_switch_bottom_right
       
open_west_right:
  sequence:
    - service: switch.turn_on
      data:
        entity_id: switch.0x00124b001d863d78_switch_top_left
    - delay:
        milliseconds: 13000
    - service: switch.turn_off     
      data:
        entity_id: switch.0x00124b001d863d78_switch_top_left
       
close_west_right:
  sequence:
    - service: switch.turn_on
      data:
        entity_id: switch.0x00124b001d863d78_switch_top_right
    - delay:
        milliseconds: 13000
    -  service: switch.turn_off    
       data:
         entity_id: switch.0x00124b001d863d78_switch_top_right
              
#########################################################
#                                                       #
#            END OF CONFIGURATION FILE                  #
#                                                       #
#########################################################       

Customisation:

switch.0x00124b001d863d78_switch_bottom_left:
  friendly_name: Lux west left ^
  icon: mdi:arrow-up-bold
switch.0x00124b001d863d78_switch_bottom_right:
  friendly_name: Lux west left 
  icon: mdi:arrow-down-bold
switch.0x00124b001d863d78_switch_top_left:
  friendly_name: Lux west right ^
  icon: mdi:arrow-up-bold
switch.0x00124b001d863d78_switch_top_right:
  friendly_name: Lux west right
  icon: mdi:arrow-down-bold
sensor.0x00124b001d863d78_linkquality:
  friendly_name: Lux west
  icon: mdi:signal  

The automation part:

#########################################################
#                                                       #
#         CLOSE LUXAFLEX WEST LEFT AT SUNSET            #
#                                                       #
#########################################################

  - alias: 'lux west left close sunset'
    initial_state: true
    trigger:
      platform: sun
      event: sunset
      offset: '+00:02:00'
    action:
      service: cover.close_cover
      entity_id: cover.lux_west_left
      
#########################################################
#                                                       #
#         OPEN  LUXAFLEX WEST LEFT AT SUNRISE        #
#                                                       #
#########################################################      
      
  - alias: 'lux west left open sunset'
    initial_state: true
    trigger:
      platform: sun
      event: sunrise
      offset: '+00:00:00'
    action:
      service: cover.open_cover
      entity_id: cover.lux_west_left

#########################################################
#                                                       #
#         CLOSE LUXAFLEX WEST RIGHT AT SUNSET           #
#                                                       #
#########################################################

  - alias: 'lux west right close sunset'
    initial_state: true
    trigger:
      platform: sun
      event: sunset
      offset: '+00:01:00'
    action:
      service: cover.close_cover
      entity_id: cover.lux_west_right
      
#########################################################
#                                                       #
#         OPEN LUXAFLEX WEST RIGHT AT SUNRISE           #
#                                                       #
#########################################################      
      
  - alias: 'lux west right open sunset'
    initial_state: true
    trigger:
      platform: sun
      event: sunrise
      offset: '+00:01:00'
    action:
      service: cover.open_cover
      entity_id: cover.lux_west_right

#########################################################
#                                                       #
#            END OF CONFIGURATION FILE                  #
#                                                       #
######################################################### 

And this is how it looks:
Screenshot 2020-02-11 at 15.49.57

Sorry for this long post, hopefully it will be of some help to others

8 Likes

After an unscheduled reboot and restart of Hassio in the evening I discovered that the status of the blinds was incorrectly set to open. After reading this forum and the help from @ Schneider Cover template last state after reboot I found the solution:

1. Create boolean:

input_boolean.yaml

 lux_west_left:
    name: "Status lux west left"  
    icon: mdi:glassdoor      
  
  lux_west_right:
    name: "Status lux west right"  
    icon: mdi:glassdoor

2. Modify the covers

#########################################################
#                                                       #
#        ZIGBEE LUXAFLEX WEST                           #
#                                                       #
#########################################################

  - platform: template
    covers:
      lux_west_left:
        value_template: "{{ is_state('input_boolean.lux_west_left', 'on') }}"
        entity_id: input_boolean.lux_west_left
        friendly_name: "Lux west left"
        open_cover:
          service: script.open_west_left
        close_cover:
          service: script.close_west_left
        stop_cover:
          service: switch.turn_off
          data:
            entity_id: 
              - switch.0x00124b001d863d78_switch_bottom_right
              - switch.0x00124b001d863d78_switch_bottom_left
          
  - platform: template
    covers:
      lux_west_right:
        value_template: "{{ is_state('input_boolean.lux_west_right', 'on') }}"
        entity_id: input_boolean.lux_west_right
        friendly_name: "Lux west right"
        open_cover:
          service: script.open_west_right
        close_cover:
          service: script.close_west_right
        stop_cover:
          service: switch.turn_off
          data:
            entity_id: 
              - switch.0x00124b001d863d78_switch_top_right
              - switch.0x00124b001d863d78_switch_top_left      
       
#########################################################
#                                                       #
#            END OF CONFIGURATION FILE                  #
#                                                       #
#########################################################   

Now you need to test your system by a restart/reboot and check if the boolean has the correct value.

I have added the booleans input_boolean.lux_west_left and input_boolean.lux_west_left to Lovelace:

Screenshot 2020-02-26 at 10.09.39

This way it is very easy to correct the status of the boolean. If the ‘boolean-switch’ in Lovelace is on, than the blinds are open. So make sure the status of the boolean mirrors the actual status of the blinds.

1 Like

Congrats, impressive project!

1 Like

There has been a breaking change in the PTVO firmware and zigbee2mqtt.
As of zigbee2mqtt 1.14.1 the above mentioned set-up no longer works. Don’t worry you only need to make some minor modifications.
So after your zigbee2mqtt has been upgraded to > 1.14.1 you will notice that the
switch.0x00124b001d863d78_switch_bottom_left no longer functions, just replace this with switch.0x00124b001d863d78_switch_l1.

switch.0x00000_switch_bottom_left => switch.0x00000_switch_l1
switch.0x00000_switch_bottom_right=>switch.0x00000_switch_l2
switch.0x00000_switch_top_left=>switch.0x00000_switch_l3
switch.0x00000_switch_top_right=>switch.0x00000_switch_l4

That’s all

Hi, I would like to create the same automation but apply it to opening and closing a window. What I don’t understand is: the motor stops in the delay set in the software but if there were an impediment what would happen? does the card stop the motor automatically or skip any protection? In case the current fails during opening, how does it return to the initial position? a thousand thanks

I have improved the automation by using the timer build in the CC2530. Perhaps this is more clear and better for you as well. So rather than sending the on/off signal from HA, it is better to use the CC2530 timer. This is more accurate. Now you only have to send a on signal for the timer. Let me show you my code:

The switch timer:

####################################################
#                                                  #
#  LUX WEST LEFT                                   #
#                                                  #
####################################################    

  - platform: mqtt
    unique_id: lux_west_left_up
    name: "Lux west left up"
    icon: mdi:blinds-open
    state_topic: "zigbee2mqtt/0x00124b001d863d78"
    command_topic: "zigbee2mqtt/0x00124b001d863d78/l1/set"   
    availability_topic: "zigbee2mqtt/bridge/state"
    payload_off: "OFF"
    payload_on: '{"trigger": 20800}'
    value_template: "{{ value_json.state_l1 }}"
    retain: true
    
  - platform: mqtt
    unique_id: lux_west_left_down
    name: "Lux west left down"
    icon: mdi:blinds
    state_topic: "zigbee2mqtt/0x00124b001d863d78"
    command_topic: "zigbee2mqtt/0x00124b001d863d78/l2/set"   
    availability_topic: "zigbee2mqtt/bridge/state"
    payload_off: "OFF"
    payload_on: '{"trigger": 20700}'
    value_template: "{{ value_json.state_l2 }}"
    retain: true    

The cover code is unchanged:

#########################################################
#                                                       #
#        ZIGBEE LUXAFLEX WEST                           #
#                                                       #
#########################################################

  - platform: template
    covers:
      lux_west_left:
        value_template: "{{ is_state('input_boolean.lux_west_left', 'on') }}"
        friendly_name: "Lux west left"
        open_cover:
          service: script.open_west_left
        close_cover:
          service: script.close_west_left
        stop_cover:
          service: switch.turn_off
          data:
            entity_id: 
              - switch.0x00124b001d863d78_switch_l1
              - switch.0x00124b001d863d78_switch_l2
        icon_template: >-
          {% if is_state('input_boolean.lux_west_left', 'off') %}
            mdi:window-shutter
          {% else %}
            mdi:window-shutter-open
          {% endif %}          
          
  - platform: template
    covers:
      lux_west_right:
        value_template: "{{ is_state('input_boolean.lux_west_right', 'on') }}"
        friendly_name: "Lux west right"
        open_cover:
          service: script.open_west_right
        close_cover:
          service: script.close_west_right
        stop_cover:
          service: switch.turn_off
          data:
            entity_id:  
              - switch.0x00124b001d863d78_switch_l3
              - switch.0x00124b001d863d78_switch_l4 
        icon_template: >-
          {% if is_state('input_boolean.lux_west_right', 'off') %}
            mdi:window-shutter
          {% else %}
            mdi:window-shutter-open
          {% endif %}          
       
#########################################################
#                                                       #
#            END OF CONFIGURATION FILE                  #
#                                                       #
#########################################################         

To give you a complete picture, here is the script code

#########################################################
#                                                       #
#        ZIGBEE LUXAFLEX WEST                           #
#                                                       #
#########################################################

open_west_left:
  sequence:
    - service: switch.turn_on
      entity_id: switch.lux_west_left_up_2
    - service: input_boolean.turn_off
      entity_id: input_boolean.lux_west_left   
      
close_west_left:
  sequence:
    - service: switch.turn_on
      entity_id: switch.lux_west_left_down_2
    - service: input_boolean.turn_on
      entity_id: input_boolean.lux_west_left     
       
open_west_right:
  sequence:
    - service: switch.turn_on
      entity_id: switch.lux_west_right_up_2
    - service: input_boolean.turn_off
      entity_id: input_boolean.lux_west_right    
       
close_west_right:
  sequence:
    - service: switch.turn_on
      entity_id: switch.lux_west_right_down_2
    - service: input_boolean.turn_on
      entity_id: input_boolean.lux_west_right      
              
#########################################################
#                                                       #
#            END OF CONFIGURATION FILE                  #
#                                                       #
#########################################################               

Thanks for the answer, I’ll try your project code! One question, what if the system is blocked by an obstacle? Does the motor stop the automatic or do you need to create a special hardware?

In my case I have just used a motor, obstacles cannot be detected.