How to control Somfy IO with a Raspberry Pi

Another blog about home automation. We added Somfy IO motorized rolling shutters to our house recently with a Situo 5 IO remote to control them. But what about controlling these rolling shutters with a Raspberry Pi, preferably without an expensive hub? I did some tinkering and found a much cheaper solution.

Somfy IO or RTS

Somfy uses two types of wireless control for motorized rolling shutters: RTS and io-homecontrol. RTS stands for Radio Technology Somfy and uses the open 433 MHz radiofrequency for one-way control. Io-homecontrol is the newer two-way wireless technology. This technology is more secure and more reliable, but this also means that it is more difficult to control with products like a Raspberry Pi.

If you have rolling shutters with an RTS wireless receiver you should look for blogs about Raspberry Pi and rf433. This blog is about controlling Somfy IO rolling shutters with a Raspberry Pi. This solution won’t work with RTS rolling shutters.

What do you need?

Well, Somfy motorized rolling shutters and a Raspberry Pi of course. But what else? You’ll find a small shopping list below.

Do you need a hub?

Somfy offers two devices for smart home control of their rolling shutters: the TaHoma hub and the Connexoon io hub. The TaHoma costs about 300 euro and the Connexoon about 170 euro. That’s quite expensive! I already use a Raspberry Pi to control most of my smart home devices and I don’t want to add another hub just to move my rolling shutters. I want to control my rolling shutters without a hub.

Other requirements

I did some Google searches and I found the Somfy Izymo transmitter module. This module is meant for people who already have a wired push-button or rocker switch that they want to transform into an io control. When I got this module it cost about 35 euro, but the price has gone up a bit to about 50 euro.

Somfy Izymo transmitter

As you’ll see below, you’ll also need a relay with at least two channels. I used this two-channel relay that cost 6,95 euro.

Two-channel relay

And finally, you’ll need some wires to connect the Raspberry Pi, the Izymo module, and the relay. You could also use a breadboard or a small terminal block to make connections without soldering. This shouldn’t cost much. I had this stuff lying around from other projects.

You’ll also need a remote to pair the Izymo transmitter to the rolling shutters. You’ll only need to do this once and you can still use the remote like a regular remote afterward.

So here’s your shopping list:

Even cheaper option

During my search for a solution, I also found some blogs about soldering a Somfy remote directly to an Arduino or a Raspberry Pi. Since a single remote is a bit cheaper than the Izymo module this option will be a bit cheaper altogether. I did not choose this option, because I don’t want to butcher a remote for this. But it is an option.

Pairing the transmitter

Before you can use the Izymo transmitter it must be paired with the rolling shutters. The easiest way is to use another remote that is already paired with the rolling shutters. There’s a small button on the back of the Situo 5 IO remote that can be used to put the rolling shutters in association mode. Then briefly press the PROG 1 button (for channel S1) or PROG 2 button (for channel S2) on the transmitter and that should be it.

Wiring schematics

As you can see in the picture, the Izymo module has three wires: green, white, and yellow. If you connect the white wire to the yellow wire, the rolling shutters go up. And if you connect the white wire to the green wire, the rolling shutters go down. So to control the rolling shutters, you need to physically ‘switch’ between these wires. That’s what we’ll use the relay for that was mentioned earlier.

The relay has four pins to connect it to the Raspberry Pi. On the relay I got, the VCC pin is connected to 5 volts, the GND pin is connected to ground and the other two pins (IN1 and IN2) are connected to the GPIO pins. In my case, I used pin 13 and 26 as GPIO pins, but feel free to use other pins if that suits your project.

Wiring schematic

A Python code example

After connecting all the wires we can start writing some code. There are plenty of blogs about using the GPIO pins on a Raspberry Pi with Python. I can recommend this blog if this is your first project: https://pythonprogramming.net/gpio-raspberry-pi-tutorials/. The code below is actually not very different from the example in the other blog.

You can change the pin numbers to correspond with your own project. Then call the function move_shutters() with a direction (‘up’ or ‘down’) and the duration in seconds that you want to move the rolling shutters.

Open In Colab

In [ ]:
import RPi.GPIO as GPIO
import time

GPIO.setmode(GPIO.BCM)

pin_up = 26
pin_down = 13

GPIO.setup(pin_up, GPIO.OUT)
GPIO.setup(pin_down, GPIO.OUT)

GPIO.output(pin_up, GPIO.LOW)
GPIO.output(pin_down, GPIO.LOW)

def move_shutters (direction, sec):
    if (direction == 'up'):
        GPIO.output(pin_up, GPIO.HIGH)
        time.sleep(sec)
        GPIO.output(pin_up, GPIO.LOW)
    if (direction == 'down'):
        GPIO.output(pin_down, GPIO.HIGH)
        time.sleep(sec)
        GPIO.output(pin_down, GPIO.LOW)

move_shutters('down', 20)

A Nodejs example

The example below is a bit more elaborate. This is what I actually use in my own home automation project. It creates a Router for a Nodejs Express app. I also added some lines to make it work on devices without GPIO pins for testing purposes.

27 Replies to “How to control Somfy IO with a Raspberry Pi”

  1. Great idea!! Thank you for sharing because I was looking on how to automate my two sunblinds with home assistant that actually I manage with a situo 5 remote. Just a question about the Zomfy Izymo module, how does it control two different blinds that works on two different channels in the situo 5 remote? Is this related to “prog1” and “prog2”? I have read the manual in internet but I still don´t understand how does it works…
    Thanks!!!

    1. Hi Jesus,
      Good question! I’m not sure if the Izymo module can be used for controlling multiple channels. I use it to control only one channel. Perhaps you can control two shutters separately if you use it to trigger scenarios if the module is in mode 1. You can use the PROG buttons to link it to a scenario in mode 1. But for my shutters, the module is set to mode 4, and then the PROG buttons are only used to connect the module to the shutters.

  2. Hi Jesus. Did you find a solution to control 2 motors with one module in the end?
    I’d like to control my 2 sunblinds as well and I feel stupid buying the superexpensive Tahoma thing.
    I regret not having bought a cheaper motor with the open 433mhz rf, but now it’s too late and they tricked me in buying the overpriced Somfy ones : (

  3. Hi Wouter, thanks for your post.
    However would you be so kind to update the link to the breadbord used please?
    Also like to get my Somfy sunscreen going but soldering isn’t my thing so hope this will work.
    cheers!

    1. Hi Seb, you can control multiple shutters with a single remote, as long as all shutters act as one. I have two shutters for example that can both go up or down at the same time with this remote.

  4. Thank you Wouter.
    I’ve used your example as inspiration and replaced the Raspberry for an ESP32 with Tasmota flash on it… Now my Somfy IO can be controlled from Home Assistant without the Somfy hub devices.

    1. Hi Onra H.,

      I am ordering the hardware needed to connect my IO rollshutters of Somfy. I also have ordered the ESP32 (Adafruit HUZZAH32 – ESP32 Breakout Board). I will try to do a similar setup as you described. Do you happen to have more information on how you set up your solution? I would be very interested, as I am not too experienced with this.

      Thanks

    1. Hi Clem, I don’t use Home Assistant myself, so I’m not sure. Sorry! One of the other comments did mention he/she got it working with Home Assistant.

  5. Hi Onra,

    Can you elaborate on the ESP32 and how to get it working with home assistant step by step? What components do we need and how to configure them to work with HA and Somfy IO.

    I am new to home assistant and tasmota.

    Thanks

    1. It’s possible to use a remote with espHome:
      The time based covers can be adjusted with correct open close duration in sec.
      I used esp32 in the first place and changed it to the esp8266

      Pictures:
      https://photos.app.goo.gl/gV5gEV2tgLHZnCLz6
      https://photos.app.goo.gl/4W9KLQznEncWVpGEA
      https://photos.app.goo.gl/4XGfJVoS8pJZB7nv7

      espHome code:

      esphome:
      name: somfy-screens-d1-mini

      esp8266:
      board: esp01_1m

      Enable logging
      logger:

      Enable Home Assistant API
      api:
      password: !secret api_password
      encryption:
      key: !secret api_encryption_key

      ota:
      password: !secret ota_password

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

      # Enable fallback hotspot (captive portal) in case wifi connection fails
      ap:
      ssid: “Somfy-Screens-Mini”
      password: “x6uCMw6K68X8”

      captive_portal:

      globals:
      – id: somfy_select_int
      type: int
      initial_value: ‘5’
      – id: select_last_modified_time
      type: int
      initial_value: ‘10000’

      switch:
      # The switch that turns the UP direction on
      – platform: gpio
      pin:
      number: GPIO14 #D5
      inverted: true
      name: esp_somfy_up
      id: somfy_up
      # Use interlocking to keep at most one of the two directions on
      interlock: &interlock_group [somfy_up, somfy_down, somfy_select, somfy_prog]
      # If ESP reboots, do not attempt to restore switch state
      restore_mode: always off

      # The switch that turns the DOWN direction on
      – platform: gpio
      pin:
      number: GPIO12 #D6
      inverted: true
      name: esp_somfy_down
      id: somfy_down
      interlock: *interlock_group
      restore_mode: always off

      # The switch that turns the MyButton on
      – platform: gpio
      pin:
      number: GPIO13 #D7
      inverted: true
      name: esp_somfy_my
      id: somfy_my
      interlock: *interlock_group
      restore_mode: always off

      # The switch that turns the Select Button on
      – platform: gpio
      pin:
      number: GPIO5 #D1
      inverted: true
      name: esp_somfy_select
      id: somfy_select
      interlock: *interlock_group
      restore_mode: always off
      on_turn_on:
      then:
      – if:
      condition:
      lambda: return (id(select_last_modified_time) > 4500);
      then:
      – script.stop: select_activation_counter
      – lambda: |-
      if (id(select_last_modified_time) > 0) {
      id(select_last_modified_time) = 0;
      } else {
      }
      – script.execute: select_activation_counter
      – delay: 1500ms
      – switch.turn_off: somfy_select
      – delay: 100ms
      – switch.turn_on: somfy_select
      else:
      – delay: 1000ms
      – script.stop: select_activation_counter
      – lambda: |-
      if (id(select_last_modified_time) > 0) {
      id(select_last_modified_time) = 0;
      } else {
      }
      – lambda: |-
      if (id(somfy_select_int) == 5) {
      id(somfy_select_int) = 1;
      } else {
      id(somfy_select_int) += 1;
      }
      – delay: 1000ms
      – switch.turn_off: somfy_select
      – delay: 100ms
      – script.execute: select_activation_counter

      # The switch that turns the prog direction on
      – platform: gpio
      pin:
      number: GPIO4 #D2
      inverted: true
      name: esp_somfy_prog
      id: somfy_prog
      # Use interlocking to keep at most one of the two directions on
      interlock: *interlock_group
      # If ESP reboots, do not attempt to restore switch state
      restore_mode: always off

      sensor:
      – platform: template
      name: esp_somfy_channel
      icon: “mdi:select”
      accuracy_decimals: 0
      lambda: !lambda |-
      if (id(somfy_select).state) {
      return id(somfy_select_int);
      } else {
      return id(somfy_select_int);
      }
      update_interval: 2sec

      cover:
      – platform: time_based
      name: “somfy zonwering_1”
      id: cover_1
      has_built_in_endstop: true
      assumed_state: false

      open_action:
      – switch.turn_on: somfy_up
      open_duration: 30sec

      close_action:
      – switch.turn_on: somfy_down
      close_duration: 28sec

      stop_action:
      – switch.turn_off: somfy_up
      – delay: 100ms
      – switch.turn_off: somfy_down
      – delay: 100ms
      – switch.turn_on: somfy_my
      – delay: 100ms
      – switch.turn_off: somfy_my
      – delay: 100ms
      platform: time_based
      name: “somfy zonwering_2”
      id: cover_2
      has_built_in_endstop: true
      assumed_state: false

      open_action:

      switch.turn_on: somfy_up open_duration: 30sec
      close_action:
      – switch.turn_on: somfy_down
      close_duration: 28sec

      stop_action:
      – switch.turn_off: somfy_up
      – delay: 100ms
      – switch.turn_off: somfy_down
      – delay: 100ms
      – switch.turn_on: somfy_my
      – delay: 100ms
      – switch.turn_off: somfy_my
      – delay: 100ms

      platform: time_based
      name: “somfy zonwering_3”
      id: cover_3
      has_built_in_endstop: true
      assumed_state: false

      open_action:

      switch.turn_on: somfy_up open_duration: 0sec
      close_action:
      – switch.turn_on: somfy_down
      close_duration: 0sec

      stop_action:
      – switch.turn_off: somfy_up
      – delay: 100ms
      – switch.turn_off: somfy_down
      – delay: 100ms
      – switch.turn_on: somfy_my
      – delay: 100ms
      – switch.turn_off: somfy_my
      – delay: 100ms

      platform: time_based
      name: “somfy zonwering_4”
      id: cover_4
      has_built_in_endstop: true
      assumed_state: false

      open_action:

      switch.turn_on: somfy_up open_duration: 0sec
      close_action:
      – switch.turn_on: somfy_down
      close_duration: 0sec

      stop_action:
      – switch.turn_off: somfy_up
      – delay: 100ms
      – switch.turn_off: somfy_down
      – delay: 100ms
      – switch.turn_on: somfy_my
      – delay: 100ms
      – switch.turn_off: somfy_my
      – delay: 100ms

      platform: time_based
      name: “somfy zonwering_5”
      id: cover_5
      has_built_in_endstop: true
      assumed_state: false

      open_action:

      switch.turn_on: somfy_up open_duration: 30sec
      close_action:
      – switch.turn_on: somfy_down
      close_duration: 28sec

      stop_action:
      – switch.turn_off: somfy_up
      – delay: 100ms
      – switch.turn_off: somfy_down
      – delay: 100ms
      – switch.turn_on: somfy_my
      – delay: 100ms
      – switch.turn_off: somfy_my
      – delay: 100ms

      script:
      – id: select_activation_counter

      mode: restart
      then:
      – repeat:
      count: 10000
      then:
      – delay: 100ms # timer length
      – lambda: |-
      if (id(select_last_modified_time) < 10000) {
      id(select_last_modified_time) += 100;
      } else {
      }

      ============================================================================================

      The Dasboard code in Home Assistant :

      type: vertical-stack
      cards:
      – type: glance
      entities:
      – entity: sensor.esp_somfy_channel
      state_color: true
      show_state: true
      show_icon: true
      show_name: false
      – type: button
      tap_action:
      action: toggle
      entity: switch.esp_somfy_select
      icon_height: 50px
      icon: mdi:select
      show_state: false
      name: Select
      – type: conditional
      conditions:
      – entity: sensor.esp_somfy_channel
      state: '1'
      card:
      type: vertical-stack
      cards:
      – type: entities
      entities:
      – entity: cover.somfy_zonwering_1
      secondary_info: position
      state_color: true
      – type: conditional
      conditions:
      – entity: sensor.esp_somfy_channel
      state: '2'
      card:
      type: vertical-stack
      cards:
      – type: entities
      entities:
      – entity: cover.somfy_zonwering_2
      secondary_info: position
      state_color: true
      – type: conditional
      conditions:
      – entity: sensor.esp_somfy_channel
      state: '3'
      card:
      type: vertical-stack
      cards:
      – type: entities
      entities:
      – entity: cover.somfy_zonwering_3
      secondary_info: position
      state_color: true
      – type: conditional
      conditions:
      – entity: sensor.esp_somfy_channel
      state: '4'
      card:
      type: vertical-stack
      cards:
      – type: entities
      entities:
      – entity: cover.somfy_zonwering_4
      secondary_info: position
      state_color: true
      – type: conditional
      conditions:
      – entity: sensor.esp_somfy_channel
      state: '5'
      card:
      type: vertical-stack
      cards:
      – type: entities
      entities:
      – entity: cover.somfy_zonwering_5
      secondary_info: position
      state_color: true
      – type: glance
      entities:
      – entity: cover.somfy_zonwering_1
      – entity: cover.somfy_zonwering_2
      – entity: cover.somfy_zonwering_3
      – entity: cover.somfy_zonwering_4
      – entity: cover.somfy_zonwering_5
      state_color: true
      show_icon: true
      show_state: true
      show_name: true

      1. Do you have this in a more readable format like yaml with correct indentations? I’m not an expert in this stuff and can’t get it to work 🙂

      2. @Peter Could I use your code with the Izymo and leave out the section for the My and Select buttons?

      3. What would be the advantage to have has_built_in_endstop: true in there?

        Obviously the relay is not going to be turned off if there is not communication back to the ESP.

    1. Hi Pieter,

      Somfy RTS uses the 433mhz protocol if I’m not mistaken. And if so, then it’s definitely possible to build something for remote control. Try searching on Google for “rpi rf 433” for example. You’ll find all the necessary parts (a sender, a receiver, and some wires) for only a couple of euros and instructions on how to connect them to a Raspberry Pi computer.

      Assuming that you’re also from the Netherlands: check this blog for a complete tutorial: https://eye-vision.homeip.net/domotica-met-raspberry-pi/

  6. Hi Wouter,
    Were you lucky to discover a magic behind the “My” button at the IO remote? Izymo transmitter doesn’t have this button neither has corresponding combination of S1+S2 button presses in docs, that replicates a behavior of “My” button.
    I don’t like to convert remote into an “interface module”, I’d use Izymo for that.
    Thank you for your efforts in this automation!
    Regards Konstantin

  7. Thanks Wouter!
    I litterally copied your example and I can now indeed open and close my Somfy shutters without the use of the remote control.

    One question I have which I dont believe has been posted here yet: This solution does not allow to read the state of the shutters, right? Or does the IZMO also ‘ read’ whether the shutter is open or closed somehow?

    Thanks anyways! I am beginner in home automation and RBPi and python… but so far enjoying it a lot!

    Steeef

  8. Hi all, thanks for the discussion.

    I assume I can do the same with a Somfy Smoove Origin io remote which I got installed at home? According to a Somfy set-up video there is also a button on the back to pair transmitters. I am also using Home Assistant at home and want to integrate it locally (not via any cloud service).

  9. Are you sure that you need the relais? I wonder if its possible to drive the S1 + S2 Pin directly to GND via the MCs IO PINs.

  10. Hi, very interesting blog!
    Is there a way to include the “my” button?
    The button has 2 functions: First you can stop the shutter while moving. Pressing the opposite direction does’nt mean “stop”.
    Second, the button also means to put the shutters into a preferred position if not moving at that time.

    Maybe I don’t get the GPIO.OUT/LOW/HIGH?
    Thanks!

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.