PLCLogo Solution: Logo Rollershutter Control

Tags: #<Tag:0x00007f616a8e9b80>

This is a wiki article and can be improved by everyone. Please do!

Problem Statement

How to control roller shutters / roller blinds / sun-blinds from Logo using wall-switches and in parallel from openHAB?

Concept

Assuming the roller shutter drive (motor) can be controlled from 2 relay-outputs of Logo. One Logo-output controls the upwards-direction, the other controls the downwards-direction. Simple roller shutters do not provide any information of the current position, but have end-switches that assure the shutter stops at the top/bottom endpoints.

Solution

Here is a screenshot of what the result looks like.
RolloShutter_sitemap

LOGO! Configuration (LOGO! SoftComfort Diagram Editor)
To control one rollo shutter the following UDF (user defined function) shall be used in your logo program.


Find the UDF for Logo7 attached RolladenMotor_L7.pdf (3.8 KB) Rename pdf to zip!
The UDF for Logo8: RolladenMotor.pdf Rename pdf to zip!

Pulse on input I_UP drives the rollo high, pulse on I_DO drives the rollo down. The time rollo must be driven, are given by UDF parameters T_UP and T_DO respectively.
As long as output O_UP is high, the rollo drives up.
O_UP goes low for the 2 following conditions:

  1. After the time T_UP has passed or
  2. O_UP is high AND new pulse is send to I_UP (manual stop).

Output IS_UP is set high, if pulse was send to I_UP and time T_UP has passed.
This works equivalent for I_DO, O_DO and IS_DO.

Additionally the UDF calculates the rollo’s position between 0 and 100 percent, as required by openHAB. Some safety is given too: It is not possible to set O_UP and O_DO high at the same time. Remember this is a software lock only. It is much better to lock the hardware additionally.

The scaling factor is not really self-explanatory. I set it to max(T_Up, T_Do) * 100. Example: If T_Up is 17 seconds and T_Do 15 seconds, then T_Sc will be 1700. That’s right: Counting is more or less precise for one direction only.
Some like, that rollos must be opened completely and closed with some gaps. Knowing each motor has physical endpoints: driving up long enough will certainly reach the upper end-point. But for driving down, the time must be measured to stop the rollo at the desired position.

In your Logo program connect the UDF like this:
RolloShutter_Logo7
The UDF (here Block U001) exposes a value named ‘Pos’, which is the current position of the rollo shutter (position is simulated and actually derived and calculated from timers).

Create a VM (variable memory) for the Pos-value, a word-value with the address 34 (as an example).
RolloShutter_Logo_VM-config

Things

Bridge plclogo:device:Logo7 "Logo7 PLC" [ address="192.168.xxx.yyy", family="0BA7", localTSAP="0x0200", remoteTSAP="0x0200", refresh=1000 ]
{
  Thing digital Inputs "Logo7 Inputs"    [ kind="I" ]
  Thing digital Outputs "Logo7 Outputs"  [ kind="Q" ]
  // Rollo1
  Thing pulse VB101_0  [ block="VB101.0", observe="VB101.0", pulse=500 ]  // NI1 rollo control-bit pulse up
  Thing pulse VB101_1  [ block="VB101.1", observe="VB101.1", pulse=500 ]  // NI2 rollo control-bit pulse down
  Thing memory VW34 [ block="VW34"]                                       // rollo position memory value-word
}

Items

Switch  RolloHi       { channel="plclogo:pulse:Logo7:VB101_0:state" } // pulse to start Rollo up
Switch  RolloDo       { channel="plclogo:pulse:Logo7:VB101_1:state" } // pulse to start Rollo down
Switch  RolloHiActive { channel="plclogo:digital:Logo7:Outputs:Q1" }  // Logo relay for motor up
Switch  RolloDoActive { channel="plclogo:digital:Logo7:Outputs:Q2" }  // Logo relay for motor down
Number  RolloPosition { channel="plclogo:memory:Logo7:VW34:value" }   // rollo's position (0% for completely open, 100% completely closed)
Rollershutter Rollo "Rollo XY" <rollershutter>

Sitemap (default.sitemap)

sitemap default label="Home" {
   Frame label="Rolloshutters" icon="attic" {
        //Default item=RolloHi 
        //Default item=RolloDo
        //Default item=RolloHiActive
        //Default item=RolloDoActive
        //Default item=RolloPosition
        Switch item=Rollo
   }
}

Rules (logo_rollo.rules)

// you may need these imports
import org.eclipse.smarthome.core.types.Command
//import org.eclipse.smarthome.core.types.RefreshType
import org.eclipse.xtext.xbase.lib.Procedures

val Procedures$Procedure4<Command, SwitchItem, SwitchItem, Command>
LogoRolloLogic = [ Command ReceivedCommand, SwitchItem Up, SwitchItem Down, Command Direction |
  switch(ReceivedCommand) {
    case UP: {
      Up.sendCommand(OnOffType.ON)
    }
    case DOWN: {
      Down.sendCommand(OnOffType.ON)
    }
    case STOP: {
      if (Direction == UP) {
        Up.sendCommand(OnOffType.ON)
      } else if (Direction == DOWN) {
        Down.sendCommand(OnOffType.ON)
      } else if (Direction != STOP) {
        logDebug("LogoRolloLogic", "Direction " + Direction + " is not supported.")
      }
    }
  }
]

rule "RolloPosChanged"
when
  Item RolloPosition changed
then
  var Number value = RolloPosition.state as Number
  Rollo.postUpdate(Math.max(Math.min(value.intValue, 100), 0))  // return a number in the range of 0 to 100.
end

rule "RolloDrive"
when
  Item Rollo received command
then
  var Command dir = STOP
  if (RolloHiActive.state == OnOffType.ON) { dir = UP }
  else if (RolloDoActive.state == OnOffType.ON) { dir = DOWN }
  LogoRolloLogic.apply(receivedCommand, RolloHi, RolloDo, dir)
end

Revision History

  • March 2019: original post for openHAB version 2.4 with Logo 0BA7

Troubleshooting

  • Rollo shutter Position behaves somehow funny.

Next Ideas

  • Hardware-Lock for outputs: One relay controls the direction and another switches power (230V) on or off.
  • The program could be extended to calculate rest time when driving from a current (known) position.
2 Likes

Concept

  • short Down-button: Q2 drives down for 5s / press again, drives down for the same time
  • long Down-button: Q2 drives down for 10s
  • short Up-button: Q1 drives up for 15s
  • short press any button any time stops motor
  • 500ms delay between changing motor direction
  • long press opposite button changes motor direction
  • continue or change direction at any time
  • emergency stop down (for door open sensor), normally LOW
  • updates Position (0% - 100%) correctly for up/down direction
  • Feature: slow update of Position (at 1s or more) good enough for polling Logo by openHAB

Solution

Here is a screenshot of what the result looks like (Basic UI):

LOGO! Configuration (LOGO! SoftComfort Diagram Editor)


FInd the UDF for Logo8 and a Logo test-program here (rename to zip): Rollershutter_L8.zip.pdf (31.7 KB)

The test-program looks like this:

Do not forget to configure the VM for the ‘Position’:
Rollershutter_LogoSoft_VM-Config

Things

Bridge plclogo:device:Logo8 "Logo8 PLC" [ address="192.168.xxx.yyy", family="0BA8", localTSAP="0x2700", remoteTSAP="0x0300", refresh=1000 ]
{
  Thing digital Inputs  "Logo8 Inputs"   [ kind="I" ]
  Thing digital Outputs "Logo8 Outputs"  [ kind="Q" ]
  
  // Rollo1
  Thing memory VW0 "Logo8 VW0"                 [ block="VW0"]      // rollo position memory value-word
  Thing memory NI1_VB100_0 "Rollo1 ButtonUp"   [ block="VB100.0", force=false ]  // NI1 rollo control-bit memory button up
  Thing memory NI2_VB100_1 "Rollo1 ButtonDown" [ block="VB100.1", force=false ] // NI2 rollo control-bit memory button down
}

Items

// Rollo1
Number  Rollo1_Position "Rollo1 Position"   { channel="plclogo:memory:Logo8:VW0:value" }    // rollo's position (0% for completely open, 100% completely closed)
Switch  Rollo1_ButtonUp     { channel="plclogo:memory:Logo8:NI1_VB100_0:state" }        // for button up
Switch  Rollo1_ButtonDown   { channel="plclogo:memory:Logo8:NI2_VB100_1:state" }        // for button down
Switch  Rollo1_goingUp      "Q5"    { channel="plclogo:digital:Logo8:Outputs:Q5" }      // Logo relay for motor up
Switch  Rollo1_goingDown    "Q6"    { channel="plclogo:digital:Logo8:Outputs:Q6" }      // Logo relay for motor down
Rollershutter Rollo1 "Rollo Room1" <rollershutter>

Rules

// 3 imports otherwise error in the line with 'Direction == UP' (ref. openHAB log)
import org.eclipse.smarthome.core.types.Command
// import org.eclipse.smarthome.core.types.RefreshType
import org.eclipse.xtext.xbase.lib.Procedures

// you need this routine only once (for multiple rollerhuttrs)
val Procedures$Procedure4<Command, SwitchItem, SwitchItem, Command>
LogoRolloLogic = [ Command ReceivedCommand, SwitchItem Up, SwitchItem Down, Command Direction |
  switch(ReceivedCommand) {
    case UP: {
      Up.sendCommand(OnOffType.ON)
      Thread::sleep(100)              // create pulse
      Up.sendCommand(OnOffType.OFF)
      logInfo("LogoRolloLogic", "Direction: " + Direction + ". UP received.")
    }
    case DOWN: {
      Down.sendCommand(OnOffType.ON)
      Thread::sleep(100)              // create pulse
      Down.sendCommand(OnOffType.OFF) 
      logInfo("LogoRolloLogic", "Direction: " + Direction + ". DOWN received.")
    }
    case STOP: { // depending on driving up or down, push the corresponding button (may avoids immediate direction change, if pulse is too long)
      logInfo("LogoRolloLogic", "Direction: " + Direction + ". STOP received.")
      if (Direction == UP) {
        Up.sendCommand(OnOffType.ON)  // perform stop by sending Up-command if going up
        Thread::sleep(100)            // create pulse
        Up.sendCommand(OnOffType.OFF)
      } else if (Direction == DOWN) {
        Down.sendCommand(OnOffType.ON)  // perform stop by sending Down-command if going down
        Thread::sleep(100)            // create pulse
        Down.sendCommand(OnOffType.OFF)
      } else if (Direction != STOP) {   // do not send an up/down command if already stopped
        logDebug("LogoRolloLogic", "Direction " + Direction + " is not supported.")
      }
    }
  }
]

// repeat the following 2 rules for each additional rollerhutter
// Rollo1
rule "Rollo1PosChanged"
when
  Item Rollo1_Position changed
then
  var Number value = Rollo1_Position.state as Number
  Rollo1.postUpdate(value.intValue)  // return Position
end

rule "Rollo1Drive" // set direction and start driving up/down 
when
  Item Rollo1 received command
then
  var Command dir = STOP
  if (Rollo1_goingUp.state == OnOffType.ON) { dir = UP }
  else if (Rollo1_goingDown.state == OnOffType.ON) { dir = DOWN }
  LogoRolloLogic.apply(receivedCommand, Rollo1_ButtonUp, Rollo1_ButtonDown, dir)
end

rule "Startup" // update the states at startup
when
   System started
then
    logInfo("StartUp", "System startup: LOGO! states flushed into (proxy) switches and variables")
    // Rolloshutters
    // must write Logo-Positions into the rollershutter item
    // *** THIS DOES NOT WORK *****
    var Number value = Rollo1_Position.state as Number
    Rollo1.postUpdate(value.intValue)
end

Sitemap

sitemap default label="Haus" {
    Frame label="Rollershutters" {
        // debug info
        Text item=Rollo1_ButtonUp   label="Rollo1_NI1_ButtonUp [%s]"    valuecolor=[OFF="red", ON="green"] icon=switch // this hides the switcher-control
        Text item=Rollo1_ButtonDown label="Rollo1_NI2_ButtonDown [%s]"  valuecolor=[OFF="red", ON="green"] icon=switch 
        Text item=Rollo1_goingUp    label="Rollo1_Q5_goingUp [%s]"      valuecolor=[OFF="red", ON="green"] icon=switch
        Text item=Rollo1_goingDown  label="Rollo1_Q6_goingDown [%s]"    valuecolor=[OFF="red", ON="green"] icon=switch
        Default item=Rollo1_Position
        // debug info
        Switch  item=Rollo1    
   }
}

Revision history

  • May 2020, openHAB 2.5.0, LOGO! 8.FS4
  • June 2020 openHAB 2.5.5-1 Release Build, LOGO! 8.FS4

Troubleshouting

  • Rollerhutter icon in sitemap flickers. I.e. if rollershutter is completely open (icon shows completely-open) and the DOWN-button is pressesd, then the icon shows completely-down status (shortly), then is updated with the actual (true) status. Similar if going UP from a middle or bottom position (icon flickers and shows completely-open shortly). (openHAB 2.5.5-1 Release Build).

Next Ideas

  • Do it yourself: All rollershuters UP button
1 Like

Thank you very much for that solution it really works fine :slight_smile:

I have a windows from floor to ceiling - approx. 2m high, so I have to adapt the parameters for that longer Rollo. But I do not understand the parameter-logic Tup Tdo1,2 TDOa,b and dont understand the scaling.

I know that the programm doesn’t run with lenght (cm) but with time needed from open to close. But how is that calculated to run to the end positions and to have the right Rollo1 Position (%) displayed in the sitemap?
As I understood, there are 2 positions to stop … Tdo1 and Tdo2 and this is handle by longer and shorter button-click?

Second question: How can I enter e.g. 70% in the sitemap to let the Rollo run to that position? is that possible?

Thanks for asking. The parameter configuration of the logo-block (UDF) is described in the test-program (my_Rollershutter_test.lsc):

  • Tup: maximum time to reach upper position (Tup > Tdo2 > Tdo1)
  • Tdo1: time to reach (1st) lower position
  • Tdo2: maximum time to reach lowest position (2nd stop) = Tdo1 + the add. time to reach maximum (end).
  • TDOa: seconds (rounded) of Tdo2
  • TDOb: seconds (rounded) of Tdo2 (sorry, must be repeated manually)
  • Scaling: Tup / Tdo2 - 0.1s (slower up-counting)

Return value is Pos = Position.

Thank you very much. I’ve seen that descriptions, but dont know how to configure in the right way.
My Roller needs
24s total down (from complete open to complete close)
26s total open (from complete close to complete open)
17s closed with gabs

my Tdo1 - first stop would be the closed roller (with gaps)
Tdo1 17s from total open to closed with gaps

I thought that should work with
Tup=26s
Tdo1=17s
Tdo2=24s
TDOa/b - this are only the steps for the position counter??
Scaling: Tup/Tdo2 - 0.1s 26/24 = 1,083s - 0.1s = 0,983

going down: the pos. counter is 100 after 8 sec
going up: the pos. counter is 0 after after 9 sec

(everything in LogoComfort Simulation)

Works perfectly for me in LogoComfort Simulation.
Tdo1 and Tdo2 must be set to 24.
Configure pulse length in block B017 (0.1 for short, 1.1 for long) and use Test NI2. Or press block I10 short/long.
Long pulse DOWN drives to Pos = 100%.
Short pulse DOWN drives to Pos = 71% (17 is 70,83% of 24)
Pulse UP always runs the longest time and assures Pos = 0%

temp

1 Like