We use cookies to personalise content and ads, to provide social media features and to analyse our traffic. We also share information about your use of our site with our social media, advertising and analytics partners who may combine it with other information that you've provided to them or that they've collected from your use of their services.

Controlling the blinds with OSCAT libraries

The Building_common.lib provided by WAGO allows for quick and simple control of blinds. However, constructing more complex functions with it is very cumbersome and requires manual work.

An alternative to that standard approach could be using the open-source OSCAT libraries maid available at ww.oscat.de. Please however be warned: if you have never worked with those libraries you might be surprised by their complexity and size as well as short documentation.  

The first difficulty you might run into while adding the oscat-basic and oscat-building libraries to your project is the 'Maximum POU number exceeded' error shown by CoDeSys and compiling/building the project.  A solution was presented by kamiKAC on our forum:

  1. After adding the above-mentioned libraries and before compiling it (which would end with an error), the "Maximum number of POUs:" in Target Setting, tab "Memory Layout" needs to be increased from the default value to more - for example 2000.  The next step is to compile the project.  When it is correctly compiled it is possible to disable/remove unused blocks from the project by going to Project->Options->Build->Exclude objects... and pressing at the bottom "Exclude unused".  The button is enabled only if the project was free of errors and built correctly.
  2. When the above ends with a success the Maximum number of POUs in Target Settings must be set back to the default value.  The project can now be compiled and uploaded to your PLC>

Many thanks to kamiKAC for this hint!

In the oscat-building library one can find many function.  When it comes to blind-controlling ones, the following are the most important:

BLIND_INPUT - to connect buttons and controlling signals

BLIND_CONTROL(_S) - to connect DO outputs controlling the blind motor


The basic functionalityy can be achieved by connecting the function block BLIND_INPUT and BLIND_CONTROL as follows:

	Input_Blind1: BLIND_INPUT;

* * *

	S1:=Button1 OR VIS_Blind1_UP , S2:=Button2 OR VIS_Blind1DN,  POS:=Control_Blind1.POS

	UP:=Input_Blind1.QU, DN:=Input_Blind1.QD,
	S_IN:=Input_Blind1.STATUS, pi:=Input_Blind1.PO\



  • Button1, Button2 - DI inputs from the wall-mounted switches,
  • VIS_ ... - variables used at visualizations,
  • OUT1, OUT2 - DI outputs controlling the motor.


The connections between BLIND_INPUT i BLIND_CONTROL_S function blocks is best presented by the graph taken from the OSCAT documentation: 

Blind Input Oscat

The beauty of the structure offered by the oscat-building library lies in the ability of connecting many function-specific function blocks like 'share control', 'night/sun control', 'alarm', 'scenes', which are placed in between INPUT and CONTROL function blocks.  It all looks like a set of LEGO block, which are placed one on another, creating a tower.

Here is an example taken directly from my installation - controlling one blind in the living room:

	Clicker_IN1 : Fb_ShortLong:=(uiTS_10tel_s:=1, uiTL_10tel_s:=1, uiT_10tel_s :=5);

	Shade_B_1S1 :BLIND_SHADE_S:=(HORZ1:=70, HORZ2:=150, SHADE_POS:=150, SHADE_DELAY:=T#60s);
	Control_B_1S1 :BLIND_CONTROL_S:=(T_UP:=T#20s, T_DN:=T#18s);

* * *

	S1:=Clicker_IN1.xShort OR VIS_B_1S1_UP, 
	S2:=Clicker_IN1.xLong OR VIS_B_1S1_DOWN, 


Where in definitions:

Clicker_IN1 - function block from WAGO Building_common.lib recognizing long/short button pushes.  A similar function in OSCAT library is in my opinion inferior. 


  • PI - the position to which the blinds should move if IN=TRUE (manual position setting),
  • MAX_RUNTIME - the maximum motor running time,
  • MANUAL_TIMEOUT - pressing a button controlling moves manually (UP/Down), will disable the automatic functions (shade, night) for 60 min,
  • MASTER_MODE - must be TRUE for the complex function block to work correctly (shade, night)


  • HORZ1 - in degrees, sun position, which, when crossed should trigger the blinds to go to the SHADE position,
  • HORZ2 - sun position, which when crossed should trigger the blinds returning to the initial position,
  • SHADE_POS - blind position in SHADE mode,
  • SHADE_DELAY - delay of reaction on changing the state of the SUN input so that the blinds do not move up/down when the sun is covered with clouds.


  • T_UP, T_DN - time needed to move the blind up and down, used to calculate the blind position.

In the program code:


  • S1 - input for UP movement, here a short press of a button connected to DI = IN1,
  • S2 - input for DN movement, here a long press of a button connected to DI = IN1,
  • IN - input for the command "move to the position set in PI", here a visualization variable,
  • POS - receiving the position from the Control_B_1S1 function block,


  • UP, DN, S_IN, pi - to be connected to Input_B_1S1 function block,
  • ENABLE - to connect a variable deciding if the function block should be taken into consideration (ON/OFF switch),
  • SUN - input for sunlight sensor,
  • CX - to connect a variable of CALENDAR type, here variable Calendar defined in a separate program ReadClock.


  • UP, DN, S_IN, pi - to be connected to Shade_B_1S1 function block.

In a separate program ReadClock (executed every 1s: Task configuration, Append Task itd.):

	Calendar_Updater : CALENDAR_CALC:=(SPE:=TRUE);
	Calendar : CALENDAR:=(LATITUDE:=51.0, LONGITUDE:=16.0, OFFSET:=120);
	Holidays :ARRAY [0..29] OF HOLIDAY_DATA;

* * *

Calendar_Updater(XCAL:=Calendar, HOLIDAYS:=Holidays);
Calendar.Utc:=SysRtcGetTime(TRUE); (*make sure your system runs at UTC time, otherwise - correct it with for example +/- T#2h*)


  • Calendar_Updater is a function block CALENDAR_CALC, which updates the calendar data,
  • Calendar - a variable of CALENDAR type, storing information about the time, sun position etc (a great thing!), OFFSET sets the difference between the local and the UTC time,
  • Holidays - an array, which should store the holidays, here empty, but needed for Calendar_Updater to work.


How does it all work?

A short press of a button connected to IN1 moves the blind UP, a long (>0.5 sec) moves it down, a short pres when motor in motion stops it.  When the sun crosses the position of 70 deg (while 90 is EAST), the blind will move to position 150 (255=open, 0=closed), when the sun moves past 150deg the blinds will move up.  Tapping the variable VIS_B_1S1_SpecPos in visualization will move the blind to position 120.  In my living room I have blinds from three directions: East, South and West - they move up and down following the sun position.


  1. All above-mentioned function block accept other configuration parameters - see the official documentation,
  2. Function blocks stored in VAR RETAIN PERSISTENT are not reset when a new program is uploaded.  Changing the configuration values in the VAR part will be ineffective.  I modify them via a visualization when the program is running.
  3. As at today (2012.07.11) BLIND_NIGHT function block ver 1.0 from oscat-building library is not in line with the documentation as if the authors published an incomplete version.

So..... good luck :)