Skip to content
  • MySensors
  • OpenHardware.io
  • Categories
  • Recent
  • Tags
  • Popular
Skins
  • Light
  • Brite
  • Cerulean
  • Cosmo
  • Flatly
  • Journal
  • Litera
  • Lumen
  • Lux
  • Materia
  • Minty
  • Morph
  • Pulse
  • Sandstone
  • Simplex
  • Sketchy
  • Spacelab
  • United
  • Yeti
  • Zephyr
  • Dark
  • Cyborg
  • Darkly
  • Quartz
  • Slate
  • Solar
  • Superhero
  • Vapor

  • Default (No Skin)
  • No Skin
Collapse
Brand Logo
  1. Home
  2. General Discussion
  3. WIndow Roller Shutter - Position

WIndow Roller Shutter - Position

Scheduled Pinned Locked Moved General Discussion
8 Posts 6 Posters 3.1k Views 6 Watching
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • SoloamS Offline
    SoloamS Offline
    Soloam
    Hardware Contributor
    wrote on last edited by
    #1

    Hello, I'm putting a automatic Window Roller Shutter at my home. I already have the system to get them up and down, and now is time to incorporate a MySensor Node. It's easy to get them up and down, just open and close a relay, but the hard part is to get the 10% open, or 50% closed (or open, depending on the point of view :) ). I was thinking on timing the open and close speed and make the math from there... but that seems like it will get it wrong eventually. Another solution would be to have some kind of sensors that would trigger checkpoints.

    Any ideas? Any one implemented something like this?

    Thank you all

    monteM 1 Reply Last reply
    0
    • scalzS Offline
      scalzS Offline
      scalz
      Hardware Contributor
      wrote on last edited by
      #2

      hi,

      what i did was to to check and recalculate/calibrate each time endstop was reached. I think most commercial devices work like this. I also had a current sensor (optional) to check motor current on endstops.
      you can take a look at

      • my code here: https://github.com/scalz/MySensors-HW/tree/development/RollerShutterNode/FW/MyRollershutter
      • or marvinroger lib is nice too: https://github.com/marvinroger/arduino-shutters
      1 Reply Last reply
      0
      • SoloamS Soloam

        Hello, I'm putting a automatic Window Roller Shutter at my home. I already have the system to get them up and down, and now is time to incorporate a MySensor Node. It's easy to get them up and down, just open and close a relay, but the hard part is to get the 10% open, or 50% closed (or open, depending on the point of view :) ). I was thinking on timing the open and close speed and make the math from there... but that seems like it will get it wrong eventually. Another solution would be to have some kind of sensors that would trigger checkpoints.

        Any ideas? Any one implemented something like this?

        Thank you all

        monteM Offline
        monteM Offline
        monte
        wrote on last edited by
        #3

        @soloam you could place a little magnet on the shaft of your roller shutter and read revolutions with a hall sensor. Then you will always know pretty accurate position of your sutter.

        1 Reply Last reply
        0
        • SoloamS Offline
          SoloamS Offline
          Soloam
          Hardware Contributor
          wrote on last edited by
          #4

          @scalz thank you for your replay, one qestion, what you use is somting like this?? :

          https://www.ebay.com/itm/181026550454?rmvSB=true
          https://www.ebay.com/itm/251558433854?rmvSB=true

          I like the idea of the auto calibration, It would make this a lot accurate!

          @monte thank you... that would be my second approach... probably an hybrid solution, use the magnets instead of the power sensor to determine the up and down positions.

          Thank You

          1 Reply Last reply
          0
          • SoloamS Offline
            SoloamS Offline
            Soloam
            Hardware Contributor
            wrote on last edited by
            #5

            Ok I found your project in openhardware.io nice work ;)

            Thank you

            1 Reply Last reply
            1
            • dbemowskD Offline
              dbemowskD Offline
              dbemowsk
              wrote on last edited by
              #6

              what type of motor are you using? If it was a stepper, just count steps, but I doubt it would be that. Maybe you could make some kind of closed loop system with a rotary encoder which should give you pretty accurate position every time.

              Vera Plus running UI7 with MySensors, Sonoffs and 1-Wire devices
              Visit my website for more Bits, Bytes and Ramblings from me: http://dan.bemowski.info/

              1 Reply Last reply
              0
              • K Offline
                K Offline
                kluszczyn
                wrote on last edited by
                #7

                Visit the following https://github.com/marvinroger/arduino-shutters

                I made one based on initial version of library, has been working for two years without any problems.

                MySensors 1.5 - 2.1.1
                MQTT Gateway based on Uno with W5100
                Openhab 2 & Node-Red

                1 Reply Last reply
                0
                • P Offline
                  P Offline
                  ppenguin
                  wrote on last edited by ppenguin
                  #8

                  I have a similar situation: my house had manually operated roller shutters, where you had to keep the button pressed to open or close them.
                  Importantly when the end stop is reached, the motor is not powered in the moving direction anymore (probably some integrated reed contact or something). If this is the case for you, my solution will work well:
                  Just make a normal arduino relay (1 for every direction) and calibrate them with a timer. Then just make sure that you add some time for the opening direction (a few seconds), it will make sure that for every cycle any drift is compensated. This even worked for me when I had to reset the system with the rollers at a certain percentage => just move up and down a few times and it's ok again.
                  In my system I have implemented the manual switches (which used to switch the 220V by connecting them with the 5V node source and switching dedicated input pins on the arduino. I have two nodes, one with 3 roller shutters and one with 1 shutter and 1 awning.
                  (I think on the 3 up/down variant, there were not enough input pins for manual input, so I had all bound to one up-down switch).

                  Here's my code (it has become somewhat messy, and if I remember correctly I changed from 100% open to 100% closed mode when changing from home assistant to openhab2):

                  /**
                     The MySensors Arduino library handles the wireless radio link and protocol
                     between your home built sensors/actuators and HA controller of choice.
                     The sensors forms a self healing radio network with optional repeaters. Each
                     repeater and gateway builds a routing tables in EEPROM which keeps track of the
                     network topology allowing messages to be routed to nodes.
                  
                     Created by Henrik Ekblad <henrik.ekblad@mysensors.org>
                     Copyright (C) 2013-2015 Sensnology AB
                     Full contributor list: https://github.com/mysensors/Arduino/graphs/contributors
                  
                     Documentation: http://www.mysensors.org
                     Support Forum: http://forum.mysensors.org
                  
                     This program is free software; you can redistribute it and/or
                     modify it under the terms of the GNU General Public License
                     version 2 as published by the Free Software Foundation.
                  
                   *******************************
                  
                     REVISION HISTORY
                     Version 0.4 - October 13, 2017 - Powerpenguin
                                   Added dedicated inputs for all manual switches
                                   (This is possible for 2 up/down actuators: D2-D5 relay, D9-D13 nRF24, A0-A3=D14-D17: switches)
                     Version 0.3 - October 9, 2017 - PowerPenguin
                  
                     DESCRIPTION
                     Based on Dimmable LED Light using PWM from Henrik Ekblad
                  
                     Simple control of window shades which are already motorised and don't provide
                     any more feedback, i.e. we want to send a target percentage from the controller
                     to the shade which then moves as tgt_percentage * time_to_fully_close
                     In the first implementation we assume that the starting state is fully open, so
                     some "drift" is to be expected? Or "overshoot" opening by a margin to make sure
                     100% corresponds to fully open? (yes: home assistant takes % open, not % closed)
                  
                     The sketch supports multiple blinds, i.e. multiple relays connected to the arduino.
                  
                     There are two relays per blind, for up/down respectively
                  
                     Also, additional pins are read for a push-button, to manually give the up or down signal
                     (will start/stop moving one or covers simultaneously, based on btcidmap[])
                  
                     To avoid the relays coils from being powered in normal operation, and most relays are active low,
                     high/low has been reversed (so high unless activated)
                     (better buy active high relays!)
                  
                     The code has become somewhat messy, better to use interrupt on manual switch? Event based?
                  
                  */
                  
                  // Enable debug prints to serial monitor
                  #define MY_DEBUG
                  
                  // Enable and select radio type attached
                  #define MY_RADIO_NRF24
                  //#define MY_RADIO_RFM69
                  
                  #include <MySensors.h>
                  
                  #define SN "WindowShades"
                  #define SV "0.4"
                  
                  #define PIN_BASE 2          // first of the Arduino pins attached to relay
                  #define LOOP_DELAY 950      // loop delay in ms
                  #define LOOP_DELAY_SMALL 30 // delay between transmissions for different sensors
                  #define PIN_BASEA 14        // base of the analog pins to be used as digital input
                  
                  #define NCOV 2              // number of covers, each have an up and down relay; maximum is half the number of available digital i/o pins
                  #define NCSW 2              // number of pairs (up/down) of manual override switches
                  enum coverstates_enum {UP, DOWN, STOPPED};
                  
                  static bool btmanup_pressed[NCSW];
                  static bool btmandn_pressed[NCSW];
                  
                  bool initialValueSent[NCOV];
                  static int8_t currentLevel[NCOV];
                  static int8_t targetLevel[NCOV];
                  static int8_t time_open[NCOV];
                  static int8_t time_close[NCOV];
                  static unsigned long tstart[NCOV];
                  static int8_t lstart[NCOV];
                  
                  // the manual button vs. CID mapping has to be specified manually, since sometimes we want one manual button to control more channels
                  static int8_t btcidmap[NCOV] = {0, 1};
                  
                  static coverstates_enum state[NCOV]; // number of values must be NCOV
                  
                  MyMessage msgPct[NCOV];
                  
                  void setup() {
                    // initialise all child actuators and related vars
                  
                    for (int8_t cid = 0; cid < NCOV; cid++) {
                      msgPct[cid] = MyMessage(cid, V_PERCENTAGE);
                      pinMode(PIN_BASE + 2 * cid, OUTPUT);
                      pinMode(PIN_BASE + 2 * cid + 1, OUTPUT);
                      state[cid] = STOPPED;
                      initialValueSent[cid] = false;
                      currentLevel[cid] = 100;
                      targetLevel[cid] = 100;
                      time_open[cid] = 29; // seconds to open, if not the same for all covers specify independently
                      time_close[cid] = 27; // seconds to close
                    }
                    // specify times independently if not the same for all covers below
                    time_close[0] = 40;
                    time_open[0] = time_close[0] + 3; // overshoot to make sure we open completely, motor stops anyway
                    time_close[1] = 26;
                    time_open[1] = time_close[1] + 3; // overshoot to make sure we open completely, motor stops anyway  
                    // time_close[2] = 22;
                    // time_open[2] = time_close[2] + 3; // overshoot to make sure we open completely, motor stops anyway  
                    
                    for (int8_t i = 0; i < NCSW; i++) {
                      pinMode(PIN_BASEA + 2 * i, OUTPUT);
                      pinMode(PIN_BASE + 2 * i + 1, OUTPUT);
                      btmanup_pressed[i] = false;
                      btmandn_pressed[i] = false;
                    }  
                  }
                  
                  
                  void presentation() {
                    // Register the Cover with the controller
                    sendSketchInfo(SN, SV);
                    for (int cid = 0; cid < NCOV; cid++) {
                      present(cid, S_COVER);
                    }
                  }
                  
                  
                  void loop() {
                  
                    int8_t cid;
                    int8_t delta;
                    
                    for (cid = 0; cid < NCOV; cid++) {
                      if (!initialValueSent[cid]) {
                        Serial.println("Sending initial value");
                        send(msgPct[cid].set(currentLevel[cid]));
                        Serial.println("Requesting initial value from controller");
                        request(cid, V_PERCENTAGE);
                        wait(LOOP_DELAY); // extra delay to give more time for initial handshake
                      } else {
                  
                        // toggle moving if manual button pressed (since we arrive heare about once a second,
                        // we don't need debounce, but we need to press the button up to 1 s to have a reaction
                        btmanup_pressed[btcidmap[cid]] = (bool)digitalRead(PIN_BASEA + 2 * btcidmap[cid]);
                        btmandn_pressed[btcidmap[cid]] = (bool)digitalRead(PIN_BASEA + 2 * btcidmap[cid] + 1);
                        // if both pressed, reset (no reaction)
                        if (btmanup_pressed[btcidmap[cid]] && btmandn_pressed[btcidmap[cid]]) btmanup_pressed[btcidmap[cid]] = btmandn_pressed[btcidmap[cid]] = false;
                        
                        if (btmanup_pressed[btcidmap[cid]]) {
                          btmanup_pressed[btcidmap[cid]] = false;
                          if (state[cid] == STOPPED) { 
                            targetLevel[cid] = 100;
                          } else { // if already moving, then stop by setting target to current
                            currentLevel[cid];
                          }
                        }
                        
                        if (btmandn_pressed[btcidmap[cid]]) {
                          btmandn_pressed[btcidmap[cid]] = false;
                          if (state[cid] == STOPPED) { // if (reference) not moving, then make go up
                            targetLevel[cid] = 0;
                          } else { // if already moving, then stop by setting target to current
                            currentLevel[cid];
                          }      
                        }
                  
                        
                        if (currentLevel[cid] > targetLevel[cid]) {   // move down (close) => means decreasing pct!
                   
                          if (state[cid] != DOWN) { // we just started going down
                            state[cid] = DOWN;
                            tstart[cid] = millis();
                            lstart[cid] = currentLevel[cid];
                            // mstotgt[cid] =  (currentLevel[cid] - targetLevel[cid]) * 10 * time_close[cid]; // remaining time to target
                          }
                  
                          digitalWrite(PIN_BASE + 2 * cid, 0);        // down pin
                          digitalWrite(PIN_BASE + 2 * cid + 1, 1);    // up pin
                          // level change over elpased time, don't exceed targetLevel (will lead to control settle behaviour)
                          currentLevel[cid] = max(lstart[cid] - (millis() - tstart[cid]) / (10 * time_close[cid]), targetLevel[cid]); 
                          Serial.print("Sending percentage feedback...");
                          Serial.println(currentLevel[cid]);
                          send(msgPct[cid].set(currentLevel[cid]));
                        } else if (currentLevel[cid] < targetLevel[cid]) {   // move up (open)
                   
                          if (state[cid] != UP) { // we just started going up
                            state[cid] = UP;
                            tstart[cid] = millis();
                            lstart[cid] = currentLevel[cid];
                            // mstotgt[cid] =  (currentLevel[cid] - targetLevel[cid]) * 10 * time_close[cid]; // remaining time to target
                          }
                  
                          digitalWrite(PIN_BASE + 2 * cid, 1);        // down pin
                          digitalWrite(PIN_BASE + 2 * cid + 1, 0);    // up pin
                          // level change over elpased time, don't exceed targetLevel (will lead to control settle behaviour)
                          currentLevel[cid] = min(lstart[cid] + (millis() - tstart[cid]) / (10 * time_open[cid]), targetLevel[cid]); 
                          Serial.print("Sending percentage feedback...");
                          Serial.println(currentLevel[cid]);
                          send(msgPct[cid].set(currentLevel[cid]));
                        } else if (currentLevel[cid] == targetLevel[cid]) {  // we always stop when the level is reached
                          // we don't change the state here, because we want to send a final level value to the controller first
                          digitalWrite(PIN_BASE + 2 * cid, 1);        // down pin
                          digitalWrite(PIN_BASE + 2 * cid + 1, 1);    // up pin
                          if (state[cid] != STOPPED) send(msgPct[cid].set(currentLevel[cid]));
                          state[cid] = STOPPED;
                        }
                        // Serial.println("Sending current level to controller");
                        // Serial.println(currentLevel[cid]);
                        // Serial.println("targetLevel = ");
                        // Serial.println(targetLevel[cid]);
                        // if (state[cid] != STOPPED) send(msgPct[cid].set(currentLevel[cid])); // send current estimated percentage back to gateway, until stopped state reached
                        // if (currentLevel[cid] != targetLevel[cid]) state[cid] = STOPPED;
                      }
                      wait(LOOP_DELAY_SMALL);
                    }
                    wait(LOOP_DELAY);
                  }
                  
                  
                  void receive(const MyMessage &message) {
                  
                    // the message sets the target value for each sensor.
                    // as long as the target is not reached, the approriate relay pin is kept high
                    // and the controller is informed every LOOP_DELAY ms about the progress
                  
                    // Serial.println("Message received from gateway (cid):");
                    // Serial.println(message.sensor);
                  
                    if (message.isAck()) {
                      Serial.println("This is an ack from gateway");
                    }
                  
                    switch (message.type) {
                      case V_PERCENTAGE:
                        if (!initialValueSent[message.sensor]) {
                          Serial.println("Receiving initial value from controller");
                          initialValueSent[message.sensor] = true;
                        }
                        targetLevel[message.sensor] = atoi(message.data);
                        targetLevel[message.sensor] = targetLevel[message.sensor] > 100 ? 100 : targetLevel[message.sensor];
                        targetLevel[message.sensor] = targetLevel[message.sensor] < 0   ? 0   : targetLevel[message.sensor];
                        Serial.println("Received V_PERCENTAGE from controller");
                        break;
                  
                      case V_UP:
                        targetLevel[message.sensor] = 100;
                        Serial.println("Received V_UP from controller");
                        break;
                  
                      case V_DOWN:
                        targetLevel[message.sensor] = 0;
                        Serial.println("Received V_DOWN from controller");
                        break;
                      case V_STOP:
                        Serial.println("Received V_STOP from controller");
                        targetLevel[message.sensor] = currentLevel[message.sensor];
                        break;
                    }
                  
                  }
                  

                  Good luck!

                  1 Reply Last reply
                  0
                  Reply
                  • Reply as topic
                  Log in to reply
                  • Oldest to Newest
                  • Newest to Oldest
                  • Most Votes


                  19

                  Online

                  11.7k

                  Users

                  11.2k

                  Topics

                  113.1k

                  Posts


                  Copyright 2025 TBD   |   Forum Guidelines   |   Privacy Policy   |   Terms of Service
                  • Login

                  • Don't have an account? Register

                  • Login or register to search.
                  • First post
                    Last post
                  0
                  • MySensors
                  • OpenHardware.io
                  • Categories
                  • Recent
                  • Tags
                  • Popular